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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seqport_util.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:33:29  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.24
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9.  /*$Id: seqport_util.cpp,v 1000.4 2004/06/01 19:33:29 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:  Clifford Clausen
  35.  *          (also reviewed/fixed/groomed by Denis Vakatov and Aaron Ucko)
  36.  *
  37.  * File Description:
  38.  */  
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbimtx.hpp>
  41. #include <objects/seq/seqport_util.hpp>
  42. #include <serial/serial.hpp>
  43. #include <serial/objostr.hpp>
  44. #include <serial/objistr.hpp>
  45. #include <objects/seq/NCBI2na.hpp>
  46. #include <objects/seq/NCBI4na.hpp>
  47. #include <objects/seq/NCBI8na.hpp>
  48. #include <objects/seq/NCBI8aa.hpp>
  49. #include <objects/seq/IUPACna.hpp>
  50. #include <objects/seq/IUPACaa.hpp>
  51. #include <objects/seq/NCBIeaa.hpp>
  52. #include <objects/seq/NCBIstdaa.hpp>
  53. #include <objects/seq/NCBIpaa.hpp>
  54. #include <objects/seqcode/Seq_code_set.hpp>
  55. #include <objects/seqcode/Seq_code_table.hpp>
  56. #include <objects/seqcode/Seq_code_type.hpp>
  57. #include <objects/seqcode/Seq_map_table.hpp>
  58. #include <util/sequtil/sequtil.hpp>
  59. #include <util/sequtil/sequtil_convert.hpp>
  60. #include <util/sequtil/sequtil_manip.hpp>
  61. #include <algorithm>
  62. #include <string.h>
  63. BEGIN_NCBI_SCOPE
  64. BEGIN_objects_SCOPE
  65. static const bool kSymbol = true;
  66. static const bool kName = false;
  67. static const unsigned int kNumCodes = 11;
  68. static inline ESeq_code_type EChoiceToESeq (CSeq_data::E_Choice from_type)
  69. {
  70.     switch (from_type) {
  71.     case CSeq_data::e_Iupacaa:
  72.         return eSeq_code_type_iupacaa;
  73.     case CSeq_data::e_Ncbi2na:
  74.         return eSeq_code_type_ncbi2na;
  75.     case CSeq_data::e_Ncbi4na:
  76.         return eSeq_code_type_ncbi4na;
  77.     case CSeq_data::e_Iupacna:
  78.         return eSeq_code_type_iupacna;
  79.     case CSeq_data::e_Ncbieaa:
  80.         return eSeq_code_type_ncbieaa;
  81.     case CSeq_data::e_Ncbistdaa:
  82.         return eSeq_code_type_ncbistdaa;
  83.     case CSeq_data::e_Ncbi8na:
  84.         return eSeq_code_type_ncbi8na;
  85.     case CSeq_data::e_Ncbipna:
  86.         return eSeq_code_type_ncbipna;
  87.     case CSeq_data::e_Ncbi8aa:
  88.         return eSeq_code_type_ncbi8aa;
  89.     case CSeq_data::e_Ncbipaa:
  90.         return eSeq_code_type_ncbipaa;
  91.     default:
  92.         throw CSeqportUtil::CBadType("EChoiceToESeq");
  93.     }
  94. }    
  95. // CSeqportUtil_implementation is a singleton.
  96. class CSeqportUtil_implementation {
  97. public:
  98.     CSeqportUtil_implementation();
  99.     ~CSeqportUtil_implementation();
  100.     
  101.     typedef CSeqportUtil::TIndex TIndex;
  102.     typedef CSeqportUtil::TPair  TPair;
  103.     TSeqPos Convert
  104.     (const CSeq_data&      in_seq,
  105.      CSeq_data*            out_seq,
  106.      CSeq_data::E_Choice   to_code,
  107.      TSeqPos               uBeginIdx,
  108.      TSeqPos               uLength,
  109.      bool                  bAmbig,
  110.      CRandom::TValue       seed)
  111.         const;
  112.     TSeqPos Pack
  113.     (CSeq_data*   in_seq,
  114.      TSeqPos      uLength)
  115.         const;
  116.     bool FastValidate
  117.     (const CSeq_data&   in_seq,
  118.      TSeqPos            uBeginIdx,
  119.      TSeqPos            uLength)
  120.         const;
  121.     void Validate
  122.     (const CSeq_data&   in_seq,
  123.      vector<TSeqPos>*   badIdx,
  124.      TSeqPos            uBeginIdx,
  125.      TSeqPos            uLength)
  126.         const;
  127.     TSeqPos GetAmbigs
  128.     (const CSeq_data&      in_seq,
  129.      CSeq_data*            out_seq,
  130.      vector<TSeqPos>*      out_indices,
  131.      CSeq_data::E_Choice   to_code,
  132.      TSeqPos               uBeginIdx,
  133.      TSeqPos               uLength)
  134.         const;
  135.     TSeqPos GetCopy
  136.     (const CSeq_data&   in_seq,
  137.      CSeq_data*         out_seq,
  138.      TSeqPos            uBeginIdx,
  139.      TSeqPos            uLength)
  140.         const;
  141.     TSeqPos Keep
  142.     (CSeq_data*   in_seq,
  143.      TSeqPos      uBeginIdx,
  144.      TSeqPos      uLength)
  145.         const;
  146.     TSeqPos Append
  147.     (CSeq_data*         out_seq,
  148.      const CSeq_data&   in_seq1,
  149.      TSeqPos            uBeginIdx1,
  150.      TSeqPos            uLength1,
  151.      const CSeq_data&   in_seq2,
  152.      TSeqPos            uBeginIdx2,
  153.      TSeqPos            uLength2)
  154.         const;
  155.     TSeqPos Complement
  156.     (CSeq_data*   in_seq,
  157.      TSeqPos      uBeginIdx,
  158.      TSeqPos      uLength)
  159.         const;
  160.     TSeqPos Complement
  161.     (const CSeq_data&   in_seq,
  162.      CSeq_data*         out_seq,
  163.      TSeqPos            uBeginIdx,
  164.      TSeqPos            uLength)
  165.         const;
  166.     TSeqPos Reverse
  167.     (CSeq_data*   in_seq,
  168.      TSeqPos      uBeginIdx,
  169.      TSeqPos      uLength)
  170.         const;
  171.     TSeqPos Reverse
  172.     (const CSeq_data&  in_seq,
  173.      CSeq_data*        out_seq,
  174.      TSeqPos           uBeginIdx,
  175.      TSeqPos           uLength)
  176.         const;
  177.     TSeqPos ReverseComplement
  178.     (CSeq_data*   in_seq,
  179.      TSeqPos      uBeginIdx,
  180.      TSeqPos      uLength)
  181.         const;
  182.     TSeqPos ReverseComplement
  183.     (const CSeq_data&   in_seq,
  184.      CSeq_data*         out_seq,
  185.      TSeqPos            uBeginIdx,
  186.      TSeqPos            uLength)
  187.         const;
  188.         
  189.     const string& GetIupacaa3(TIndex ncbistdaa);
  190.     
  191.     bool IsCodeAvailable(CSeq_data::E_Choice code_type);
  192.     
  193.     bool IsCodeAvailable(ESeq_code_type code_type);
  194.     
  195.     TPair GetCodeIndexFromTo(CSeq_data::E_Choice code_type);
  196.     
  197.     TPair GetCodeIndexFromTo(ESeq_code_type code_type);
  198.     
  199.     const string& GetCodeOrName(CSeq_data::E_Choice code_type, 
  200.                                 TIndex              idx,
  201.                                 bool                get_code); 
  202.                  
  203.     const string& GetCodeOrName(ESeq_code_type code_type, 
  204.                                 TIndex         idx,
  205.                                 bool           get_code); 
  206.                  
  207.     TIndex GetIndex(CSeq_data::E_Choice code_type,
  208.                     const string&       code);
  209.     TIndex GetIndex(ESeq_code_type code_type,
  210.                     const string&       code);
  211.                   
  212.     TIndex GetIndexComplement(CSeq_data::E_Choice code_type,
  213.                               TIndex              idx);
  214.                            
  215.     TIndex GetIndexComplement(ESeq_code_type code_type,
  216.                               TIndex         idx);
  217.     TIndex GetMapToIndex(CSeq_data::E_Choice from_type,
  218.                          CSeq_data::E_Choice to_type,
  219.                          TIndex              from_idx);
  220.     TIndex GetMapToIndex(ESeq_code_type from_type,
  221.                          ESeq_code_type to_type,
  222.                          TIndex         from_idx);
  223. private:
  224.     // Template wrapper class used to create data type specific
  225.     // classes to delete code tables on exit from main
  226.     template <class T>
  227.     class CWrapper_table : public CObject
  228.     {
  229.     public:
  230.         CWrapper_table(int size, int start)
  231.         {
  232.             m_Table   = new T[256];
  233.             m_StartAt = start;
  234.             m_Size    = size;
  235.         }
  236.         ~CWrapper_table() {
  237.             drop_table();
  238.         }
  239.         void drop_table()
  240.         {
  241.             delete[] m_Table;
  242.             m_Table = 0;
  243.         }
  244.         T*  m_Table;
  245.         int m_StartAt;
  246.         int m_Size;
  247.     };
  248.     // Template wrapper class used for two-dimensional arrays.
  249.     template <class T>
  250.     class CWrapper_2D : public CObject
  251.     {
  252.     public:
  253.         CWrapper_2D(int size1, int start1, int size2, int start2)
  254.         {
  255.             m_Size_D1 = size1;
  256.             m_Size_D2 = size2;
  257.             m_StartAt_D1 = start1;
  258.             m_StartAt_D2 = start2;
  259.             m_Table = new T*[size1];
  260.             for(int i=0; i<size1; i++)
  261.                 {
  262.                     m_Table[i] = new T[size2] - start2;
  263.                 }
  264.             m_Table -= start1;
  265.         }
  266.         ~CWrapper_2D()
  267.         {
  268.             m_Table += m_StartAt_D1;
  269.             for(int i=0; i<m_Size_D1; i++)
  270.                 {
  271.                     delete[](m_Table[i] + m_StartAt_D2);
  272.                 }
  273.             delete[] m_Table;
  274.         }
  275.         T** m_Table;
  276.         int m_Size_D1;
  277.         int m_Size_D2;
  278.         int m_StartAt_D1;
  279.         int m_StartAt_D2;
  280.     };
  281.     // Typedefs making use of wrapper classes above.
  282.     typedef CWrapper_table<char>           CCode_table;
  283.     typedef CWrapper_table<string>         CCode_table_str;
  284.     typedef CWrapper_table<int>            CMap_table;
  285.     typedef CWrapper_table<unsigned int>   CFast_table4;
  286.     typedef CWrapper_table<unsigned short> CFast_table2;
  287.     typedef CWrapper_table<unsigned char>  CAmbig_detect;
  288.     typedef CWrapper_table<char>           CCode_comp;
  289.     typedef CWrapper_table<char>           CCode_rev;
  290.     typedef CWrapper_2D<unsigned char>     CFast_4_1;
  291.     typedef CWrapper_2D<unsigned char>     CFast_2_1;
  292.     // String to initialize CSeq_code_set
  293.     // This string is initialized in seqport_util.h
  294.     static const char* sm_StrAsnData[];
  295.     // CSeq_code_set member holding code and map table data
  296.     CRef<CSeq_code_set> m_SeqCodeSet;
  297.     // Helper function used internally to initialize m_SeqCodeSet
  298.     CRef<CSeq_code_set> Init();
  299.     // Member variables holding code tables
  300.     CRef<CCode_table> m_Iupacna;
  301.     CRef<CCode_table> m_Ncbieaa;
  302.     CRef<CCode_table> m_Ncbistdaa;
  303.     CRef<CCode_table> m_Iupacaa;
  304.     // Helper function to initialize code tables
  305.     CRef<CCode_table> InitCodes(ESeq_code_type code_type);
  306.     // Member variables holding na complement information
  307.     CRef<CCode_comp> m_Iupacna_complement;
  308.     CRef<CCode_comp> m_Ncbi2naComplement;
  309.     CRef<CCode_comp> m_Ncbi4naComplement;
  310.     // Helper functions to initialize complement tables
  311.     CRef<CCode_comp> InitIupacnaComplement();
  312.     CRef<CCode_comp> InitNcbi2naComplement();
  313.     CRef<CCode_comp> InitNcbi4naComplement();
  314.     // Member variables holding na reverse information
  315.     // Used to reverse residues packed within a byte.
  316.     CRef<CCode_rev> m_Ncbi2naRev;
  317.     CRef<CCode_rev> m_Ncbi4naRev;
  318.     // Helper functions to initialize reverse tables
  319.     CRef<CCode_rev> InitNcbi2naRev();
  320.     CRef<CCode_rev> InitNcbi4naRev();
  321.     // Member variables holding map tables
  322.     
  323.     CRef<CMap_table> m_Ncbi2naIupacna;
  324.     CRef<CMap_table> m_Ncbi2naNcbi4na;
  325.     CRef<CMap_table> m_Ncbi4naIupacna;
  326.     CRef<CMap_table> m_IupacnaNcbi2na;
  327.     CRef<CMap_table> m_IupacnaNcbi4na;
  328.     CRef<CMap_table> m_Ncbi4naNcbi2na;
  329.     CRef<CMap_table> m_IupacaaNcbieaa;
  330.     CRef<CMap_table> m_NcbieaaIupacaa;
  331.     CRef<CMap_table> m_IupacaaNcbistdaa;
  332.     CRef<CMap_table> m_NcbieaaNcbistdaa;
  333.     CRef<CMap_table> m_NcbistdaaNcbieaa;
  334.     CRef<CMap_table> m_NcbistdaaIupacaa;
  335.     
  336.     TSeqPos x_ConvertAmbig
  337.     (const CSeq_data&      in_seq,
  338.      CSeq_data*            out_seq,
  339.      CSeq_data::E_Choice   to_code,
  340.      TSeqPos               uBeginIdx,
  341.      TSeqPos               uLength,
  342.      CRandom::TValue       seed)
  343.         const;
  344.     // Helper function to initialize map tables
  345.     CRef<CMap_table> InitMaps(ESeq_code_type from_type,
  346.                               ESeq_code_type to_type);
  347.     // Member variables holding fast conversion tables
  348.     // Takes a byte as an index and returns a unsigned int with
  349.     // 4 characters, each character being one of ATGC
  350.     //CRef<CFast_table4> m_FastNcbi2naIupacna;
  351.     // Takes a byte (each byte with 4 Ncbi2na codes) as an index and
  352.     // returns a Unit2 with 2 bytes, each byte formated as 2 Ncbi4na codes
  353.     //CRef<CFast_table2> m_FastNcbi2naNcbi4na;
  354.     // Takes a byte (each byte with 2 Ncbi4na codes) as an index and
  355.     // returns a 2 byte string, each byte with an Iupacna code.
  356.     //CRef<CFast_table2> m_FastNcbi4naIupacna;
  357.     // Table used for fast compression from Iupacna to Ncbi2na (4 bytes to 1
  358.     // byte). This table is a 2 dimensional table. The first dimension
  359.     // corresponds to the iupacna position modulo 4 (0-3). The second dimension
  360.     //  is the value of the iupacna byte (0-255). The 4 resulting values from 4
  361.     // iupancna bytes are bitwise or'd to produce 1 byte.
  362.     CRef<CFast_4_1> m_FastIupacnaNcbi2na;
  363.     // Table used for fast compression from Iupacna to Ncbi4na
  364.     // (2 bytes to 1 byte). Similar to m_FastIupacnaNcbi2na
  365.     CRef<CFast_2_1> m_FastIupacnaNcbi4na;
  366.     // Table used for fast compression from Ncbi4na to Ncbi2na
  367.     // (2 bytes to 1 byte). Similar to m_FastIupacnaNcbi4na
  368.     CRef<CFast_2_1> m_FastNcbi4naNcbi2na;
  369.     
  370.     // Tables used to convert an index for a code type to a symbol or name
  371.     // for the same code type
  372.     vector<vector<string> > m_IndexString[2];
  373.     vector<vector<TIndex> > m_IndexComplement;
  374.     vector<map<string, TIndex> > m_StringIndex;
  375.     vector<TIndex> m_StartAt;
  376.         
  377.     // Helper function to initialize fast conversion tables
  378.     //CRef<CFast_table4> InitFastNcbi2naIupacna();
  379.     CRef<CFast_table2> InitFastNcbi2naNcbi4na();
  380.     CRef<CFast_table2> InitFastNcbi4naIupacna();
  381.     CRef<CFast_4_1>    InitFastIupacnaNcbi2na();
  382.     CRef<CFast_2_1>    InitFastIupacnaNcbi4na();
  383.     CRef<CFast_2_1>    InitFastNcbi4naNcbi2na();
  384.     
  385.     // Helper functions to initialize Index to/from code/name conversion tables
  386.     // and complement tables 
  387.     void               InitIndexCodeName();
  388.     
  389.     // Data members and functions used for random disambiguation
  390.     // structure used for ncbi4na --> ncbi2na
  391.     struct SMasksArray : public CObject
  392.     {
  393.         // Structure to hold all masks applicable to an input byte
  394.         struct SMasks {
  395.             int           nMasks;
  396.             unsigned char cMask[16];
  397.         };
  398.         SMasks m_Table[256];
  399.     };
  400.     CRef<SMasksArray> m_Masks;
  401.     // Helper function to initialize m_Masks
  402.     CRef<SMasksArray> InitMasks();
  403.     // Data members used for detecting ambiguities
  404.     // Data members used by GetAmbig methods to get a list of
  405.     // ambiguities resulting from alphabet conversions
  406.     CRef<CAmbig_detect> m_DetectAmbigNcbi4naNcbi2na;
  407.     CRef<CAmbig_detect> m_DetectAmbigIupacnaNcbi2na;
  408.     // Helper functiond to initialize m_Detect_Ambig_ data members
  409.     CRef<CAmbig_detect> InitAmbigNcbi4naNcbi2na();
  410.     CRef<CAmbig_detect> InitAmbigIupacnaNcbi2na();
  411.     // Alphabet conversion functions. Functions return
  412.     // the number of converted codes.
  413.     /*
  414.     // Fuction to convert ncbi2na (1 byte) to iupacna (4 bytes)
  415.     TSeqPos MapNcbi2naToIupacna(const CSeq_data&  in_seq,
  416.                                 CSeq_data*        out_seq,
  417.                                 TSeqPos           uBeginIdx,
  418.                                 TSeqPos           uLength)
  419.         const;
  420.     // Function to convert ncbi2na (1 byte) to ncbi4na (2 bytes)
  421.     TSeqPos MapNcbi2naToNcbi4na(const CSeq_data&  in_seq,
  422.                                 CSeq_data*        out_seq,
  423.                                 TSeqPos           uBeginIdx,
  424.                                 TSeqPos           uLength)
  425.         const;
  426.     // Function to convert ncbi4na (1 byte) to iupacna (2 bytes)
  427.     TSeqPos MapNcbi4naToIupacna(const CSeq_data& in_seq,
  428.                                 CSeq_data*       out_seq,
  429.                                 TSeqPos          uBeginIdx,
  430.                                 TSeqPos          uLength)
  431.         const;
  432.     */
  433.     // Function to convert iupacna (4 bytes) to ncbi2na (1 byte)
  434.     TSeqPos MapIupacnaToNcbi2na(const CSeq_data& in_seq,
  435.                                 CSeq_data*       out_seq,
  436.                                 TSeqPos          uBeginIdx,
  437.                                 TSeqPos          uLength,
  438.                                 bool             bAmbig,
  439.                                 CRandom::TValue  seed)
  440.         const;
  441.     /*
  442.     // Function to convert iupacna (2 bytes) to ncbi4na (1 byte)
  443.     TSeqPos MapIupacnaToNcbi4na(const CSeq_data& in_seq,
  444.                                 CSeq_data*       out_seq,
  445.                                 TSeqPos          uBeginIdx,
  446.                                 TSeqPos          uLength)
  447.         const;
  448.     */
  449.     // Function to convert ncbi4na (2 bytes) to ncbi2na (1 byte)
  450.     TSeqPos MapNcbi4naToNcbi2na(const CSeq_data& in_seq,
  451.                                 CSeq_data*       out_seq,
  452.                                 TSeqPos          uBeginIdx,
  453.                                 TSeqPos          uLength,
  454.                                 bool             bAmbig,
  455.                                 CRandom::TValue  seed)
  456.         const;
  457.     /*
  458.     // Function to convert iupacaa (byte) to ncbieaa (byte)
  459.     TSeqPos MapIupacaaToNcbieaa(const CSeq_data& in_seq,
  460.                                 CSeq_data*       out_seq,
  461.                                 TSeqPos          uBeginIdx,
  462.                                 TSeqPos          uLength) const;
  463.     // Function to convert ncbieaa (byte) to iupacaa (byte)
  464.     TSeqPos MapNcbieaaToIupacaa(const CSeq_data& in_seq,
  465.                                 CSeq_data*       out_seq,
  466.                                 TSeqPos          uBeginIdx,
  467.                                 TSeqPos          uLength)
  468.         const;
  469.     // Function to convert iupacaa (byte) to ncbistdaa (byte)
  470.     TSeqPos MapIupacaaToNcbistdaa(const CSeq_data& in_seq,
  471.                                   CSeq_data*       out_seq,
  472.                                   TSeqPos          uBeginIdx,
  473.                                   TSeqPos          uLength)
  474.         const;
  475.     // Function to convert ncbieaa (byte) to ncbistdaa (byte)
  476.     TSeqPos MapNcbieaaToNcbistdaa(const CSeq_data& in_seq,
  477.                                   CSeq_data*       out_seq,
  478.                                   TSeqPos          uBeginIdx,
  479.                                   TSeqPos          uLength)
  480.         const;
  481.     // Function to convert ncbistdaa (byte) to ncbieaa (byte)
  482.     TSeqPos MapNcbistdaaToNcbieaa(const CSeq_data& in_seq,
  483.                                   CSeq_data*       out_seq,
  484.                                   TSeqPos          uBeginIdx,
  485.                                   TSeqPos          uLength)
  486.         const;
  487.     // Function to convert ncbistdaa (byte) to iupacaa (byte)
  488.     TSeqPos MapNcbistdaaToIupacaa(const CSeq_data& in_seq,
  489.                                   CSeq_data*       out_seq,
  490.                                   TSeqPos          uBeginIdx,
  491.                                   TSeqPos          uLength)
  492.         const;
  493.         */
  494.     // Fast Validation functions
  495.     bool FastValidateIupacna(const CSeq_data& in_seq,
  496.                              TSeqPos          uBeginIdx,
  497.                              TSeqPos          uLength)
  498.         const;
  499.     bool FastValidateNcbieaa(const CSeq_data& in_seq,
  500.                              TSeqPos          uBeginIdx,
  501.                              TSeqPos          uLength)
  502.         const;
  503.     bool FastValidateNcbistdaa(const CSeq_data& in_seq,
  504.                                TSeqPos          uBeginIdx,
  505.                                TSeqPos          uLength)
  506.         const;
  507.     bool FastValidateIupacaa(const CSeq_data& in_seq,
  508.                              TSeqPos          uBeginIdx,
  509.                              TSeqPos          uLength)
  510.         const;
  511.     // Full Validation functions
  512.     void ValidateIupacna(const CSeq_data&       in_seq,
  513.                          vector<TSeqPos>*       badIdx,
  514.                          TSeqPos                uBeginIdx,
  515.                          TSeqPos                uLength)
  516.         const;
  517.     void ValidateNcbieaa(const CSeq_data&       in_seq,
  518.                          vector<TSeqPos>*       badIdx,
  519.                          TSeqPos                uBeginIdx,
  520.                          TSeqPos                uLength)
  521.         const;
  522.     void ValidateNcbistdaa(const CSeq_data&       in_seq,
  523.                            vector<TSeqPos>*       badIdx,
  524.                            TSeqPos                uBeginIdx,
  525.                            TSeqPos                uLength)
  526.         const;
  527.     void ValidateIupacaa(const CSeq_data&       in_seq,
  528.                          vector<TSeqPos>*       badIdx,
  529.                          TSeqPos                uBeginIdx,
  530.                          TSeqPos                uLength)
  531.         const;
  532.     // Functions to make copies of the different types of sequences
  533.     TSeqPos GetNcbi2naCopy(const CSeq_data& in_seq,
  534.                            CSeq_data*       out_seq,
  535.                            TSeqPos          uBeginIdx,
  536.                            TSeqPos          uLength)
  537.         const;
  538.     TSeqPos GetNcbi4naCopy(const CSeq_data& in_seq,
  539.                            CSeq_data*       out_seq,
  540.                            TSeqPos          uBeginIdx,
  541.                            TSeqPos          uLength)
  542.         const;
  543.     TSeqPos GetIupacnaCopy(const CSeq_data& in_seq,
  544.                            CSeq_data*       out_seq,
  545.                            TSeqPos          uBeginIdx,
  546.                            TSeqPos          uLength)
  547.         const;
  548.     TSeqPos GetNcbieaaCopy(const CSeq_data& in_seq,
  549.                            CSeq_data*       out_seq,
  550.                            TSeqPos          uBeginIdx,
  551.                            TSeqPos          uLength)
  552.         const;
  553.     TSeqPos GetNcbistdaaCopy(const CSeq_data& in_seq,
  554.                              CSeq_data*       out_seq,
  555.                              TSeqPos          uBeginIdx,
  556.                              TSeqPos          uLength)
  557.         const;
  558.     TSeqPos GetIupacaaCopy(const CSeq_data& in_seq,
  559.                            CSeq_data*       out_seq,
  560.                            TSeqPos          uBeginIdx,
  561.                            TSeqPos          uLength)
  562.         const;
  563.     // Function to adjust uBeginIdx to lie on an in_seq byte boundary
  564.     // and uLength to lie on on an out_seq byte boundary. Returns
  565.     // overhang, the number of out seqs beyond byte boundary determined
  566.     // by uBeginIdx + uLength
  567.     TSeqPos Adjust(TSeqPos* uBeginIdx,
  568.                    TSeqPos* uLength,
  569.                    TSeqPos  uInSeqBytes,
  570.                    TSeqPos  uInSeqsPerByte,
  571.                    TSeqPos  uOutSeqsPerByte)
  572.         const;
  573.     // GetAmbig methods
  574.     // Loops through an ncbi4na input sequence and determines
  575.     // the ambiguities that would result from conversion to an ncbi2na sequence
  576.     // On return, out_seq contains the ncbi4na bases that become ambiguous and
  577.     // out_indices contains the indices of the abiguous bases in in_seq
  578.     TSeqPos GetAmbigs_ncbi4na_ncbi2na(const CSeq_data&  in_seq,
  579.                                       CSeq_data*        out_seq,
  580.                                       vector<TSeqPos>*  out_indices,
  581.                                       TSeqPos           uBeginIdx,
  582.                                       TSeqPos           uLength)
  583.         const;
  584.     // Loops through an iupacna input sequence and determines
  585.     // the ambiguities that would result from conversion to an ncbi2na sequence
  586.     // On return, out_seq contains the iupacna bases that become ambiguous and
  587.     // out_indices contains the indices of the abiguous bases in in_seq. The
  588.     // return is the number of ambiguities found.
  589.     TSeqPos GetAmbigs_iupacna_ncbi2na(const CSeq_data&  in_seq,
  590.                                       CSeq_data*        out_seq,
  591.                                       vector<TSeqPos>*  out_indices,
  592.                                       TSeqPos           uBeginIdx,
  593.                                       TSeqPos           uLength)
  594.         const;
  595.     // Methods to perform Keep on specific seq types. Methods
  596.     // return length of kept sequence.
  597.     TSeqPos KeepNcbi2na(CSeq_data*  in_seq,
  598.                         TSeqPos     uBeginIdx,
  599.                         TSeqPos     uLength)
  600.         const;
  601.     TSeqPos KeepNcbi4na(CSeq_data*  in_seq,
  602.                         TSeqPos     uBeginIdx,
  603.                         TSeqPos     uLength)
  604.         const;
  605.     TSeqPos KeepIupacna(CSeq_data*  in_seq,
  606.                         TSeqPos     uBeginIdx,
  607.                         TSeqPos     uLength)
  608.         const;
  609.     TSeqPos KeepNcbieaa(CSeq_data*  in_seq,
  610.                         TSeqPos     uBeginIdx,
  611.                         TSeqPos     uLength)
  612.         const;
  613.     TSeqPos KeepNcbistdaa(CSeq_data*  in_seq,
  614.                           TSeqPos     uBeginIdx,
  615.                           TSeqPos     uLength)
  616.         const;
  617.     TSeqPos KeepIupacaa(CSeq_data*  in_seq,
  618.                         TSeqPos     uBeginIdx,
  619.                         TSeqPos     uLength)
  620.         const;
  621.     // Methods to complement na sequences
  622.     // In place methods. Return number of complemented residues.
  623.     TSeqPos ComplementIupacna(CSeq_data*  in_seq,
  624.                               TSeqPos     uBeginIdx,
  625.                               TSeqPos    uLength)
  626.         const;
  627.     TSeqPos ComplementNcbi2na(CSeq_data*  in_seq,
  628.                               TSeqPos     uBeginIdx,
  629.                               TSeqPos     uLength)
  630.         const;
  631.     TSeqPos ComplementNcbi4na(CSeq_data*  in_seq,
  632.                               TSeqPos     uBeginIdx,
  633.                               TSeqPos     uLength)
  634.         const;
  635.     // Complement in copy methods
  636.     TSeqPos ComplementIupacna(const CSeq_data&  in_seq,
  637.                               CSeq_data*        out_seq,
  638.                               TSeqPos           uBeginIdx,
  639.                               TSeqPos           uLength)
  640.         const;
  641.     TSeqPos ComplementNcbi2na(const CSeq_data&  in_seq,
  642.                               CSeq_data*        out_seq,
  643.                               TSeqPos           uBeginIdx,
  644.                               TSeqPos           uLength)
  645.         const;
  646.     TSeqPos ComplementNcbi4na(const CSeq_data&  in_seq,
  647.                               CSeq_data*        out_seq,
  648.                               TSeqPos           uBeginIdx,
  649.                               TSeqPos           uLength)
  650.         const;
  651.     // Methods to reverse na sequences
  652.     // In place methods
  653.     TSeqPos ReverseIupacna(CSeq_data*  in_seq,
  654.                            TSeqPos     uBeginIdx,
  655.                            TSeqPos     uLength)
  656.         const;
  657.     TSeqPos ReverseNcbi2na(CSeq_data*  in_seq,
  658.                            TSeqPos     uBeginIdx,
  659.                            TSeqPos     uLength)
  660.         const;
  661.     TSeqPos ReverseNcbi4na(CSeq_data*  in_seq,
  662.                            TSeqPos     uBeginIdx,
  663.                            TSeqPos     uLength)
  664.         const;
  665.     // Reverse in copy methods
  666.     TSeqPos ReverseIupacna(const CSeq_data&  in_seq,
  667.                            CSeq_data*        out_seq,
  668.                            TSeqPos           uBeginIdx,
  669.                            TSeqPos           uLength)
  670.         const;
  671.     TSeqPos ReverseNcbi2na(const CSeq_data&  in_seq,
  672.                            CSeq_data*        out_seq,
  673.                            TSeqPos           uBeginIdx,
  674.                            TSeqPos           uLength)
  675.         const;
  676.     TSeqPos ReverseNcbi4na(const CSeq_data&  in_seq,
  677.                            CSeq_data*        out_seq,
  678.                            TSeqPos           uBeginIdx,
  679.                            TSeqPos           uLength)
  680.         const;
  681.  
  682.     // Methods to reverse-complement an na sequences
  683.     // In place methods
  684.     TSeqPos ReverseComplementIupacna(CSeq_data*  in_seq,
  685.                                      TSeqPos     uBeginIdx,
  686.                                      TSeqPos     uLength)
  687.         const;
  688.     TSeqPos ReverseComplementNcbi2na(CSeq_data*  in_seq,
  689.                                      TSeqPos     uBeginIdx,
  690.                                      TSeqPos     uLength)
  691.         const;
  692.     TSeqPos ReverseComplementNcbi4na(CSeq_data*  in_seq,
  693.                                      TSeqPos     uBeginIdx,
  694.                                      TSeqPos     uLength)
  695.         const;
  696.     // Reverse in copy methods
  697.     TSeqPos ReverseComplementIupacna(const CSeq_data& in_seq,
  698.                                      CSeq_data*       out_seq,
  699.                                      TSeqPos          uBeginIdx,
  700.                                      TSeqPos          uLength)
  701.         const;
  702.     TSeqPos ReverseComplementNcbi2na(const CSeq_data& in_seq,
  703.                                      CSeq_data*       out_seq,
  704.                                      TSeqPos          uBeginIdx,
  705.                                      TSeqPos          uLength)
  706.         const;
  707.     TSeqPos ReverseComplementNcbi4na(const CSeq_data& in_seq,
  708.                                      CSeq_data*       out_seq,
  709.                                      TSeqPos          uBeginIdx,
  710.                                      TSeqPos          uLength)
  711.         const;
  712.     // Append methods
  713.     TSeqPos AppendIupacna(CSeq_data*        out_seq,
  714.                           const CSeq_data&  in_seq1,
  715.                           TSeqPos           uBeginIdx1,
  716.                           TSeqPos           uLength1,
  717.                           const CSeq_data&  in_seq2,
  718.                           TSeqPos           uBeginIdx2,
  719.                           TSeqPos           uLength2)
  720.         const;
  721.     TSeqPos AppendNcbi2na(CSeq_data*          out_seq,
  722.                           const CSeq_data&  in_seq1,
  723.                           TSeqPos           uBeginIdx1,
  724.                           TSeqPos           uLength1,
  725.                           const CSeq_data&  in_seq2,
  726.                           TSeqPos           uBeginIdx2,
  727.                           TSeqPos           uLength2)
  728.         const;
  729.     TSeqPos AppendNcbi4na(CSeq_data*          out_seq,
  730.                           const CSeq_data&  in_seq1,
  731.                           TSeqPos           uBeginIdx1,
  732.                           TSeqPos           uLength1,
  733.                           const CSeq_data&  in_seq2,
  734.                           TSeqPos           uBeginIdx2,
  735.                           TSeqPos           uLength2)
  736.         const;
  737.     TSeqPos AppendNcbieaa(CSeq_data*          out_seq,
  738.                           const CSeq_data&  in_seq1,
  739.                           TSeqPos           uBeginIdx1,
  740.                           TSeqPos           uLength1,
  741.                           const CSeq_data&  in_seq2,
  742.                           TSeqPos           uBeginIdx2,
  743.                           TSeqPos           uLength2)
  744.         const;
  745.     TSeqPos AppendNcbistdaa(CSeq_data*        out_seq,
  746.                           const CSeq_data&  in_seq1,
  747.                           TSeqPos           uBeginIdx1,
  748.                           TSeqPos           uLength1,
  749.                           const CSeq_data&  in_seq2,
  750.                           TSeqPos           uBeginIdx2,
  751.                           TSeqPos           uLength2)
  752.         const;
  753.     TSeqPos AppendIupacaa(CSeq_data*          out_seq,
  754.                           const CSeq_data&  in_seq1,
  755.                           TSeqPos           uBeginIdx1,
  756.                           TSeqPos           uLength1,
  757.                           const CSeq_data&  in_seq2,
  758.                           TSeqPos           uBeginIdx2,
  759.                           TSeqPos           uLength2)
  760.         const;
  761.     void x_GetSeqFromSeqData(const CSeq_data& data, 
  762.                              const string** str,
  763.                              const vector<char>** vec)
  764.         const;
  765.     void x_GetSeqFromSeqData(CSeq_data& data, 
  766.                              string** str,
  767.                              vector<char>** vec)
  768.         const;
  769. };
  770. auto_ptr<CSeqportUtil_implementation> CSeqportUtil::sm_Implementation;
  771. DEFINE_STATIC_FAST_MUTEX(init_implementation_mutex); /* put back inside x_InitImplementation after Mac CodeWarrior 9.0 comes out */
  772. void CSeqportUtil::x_InitImplementation(void)
  773. {
  774.     CFastMutexGuard   LOCK(init_implementation_mutex);
  775.     if ( !sm_Implementation.get() ) {
  776.         sm_Implementation.reset(new CSeqportUtil_implementation());
  777.     }
  778. }
  779. /////////////////////////////////////////////////////////////////////////////
  780. //  PUBLIC (static wrappers to CSeqportUtil_implementation public methods)::
  781. //
  782. TSeqPos CSeqportUtil::Convert
  783. (const CSeq_data&     in_seq,
  784.  CSeq_data*           out_seq,
  785.  CSeq_data::E_Choice  to_code,
  786.  TSeqPos              uBeginIdx,
  787.  TSeqPos              uLength,
  788.  bool                 bAmbig,
  789.  CRandom::TValue      seed)
  790. {
  791.     return x_GetImplementation().Convert
  792.         (in_seq, out_seq, to_code, uBeginIdx, uLength, bAmbig, seed);
  793. }
  794. TSeqPos CSeqportUtil::Pack
  795. (CSeq_data*   in_seq,
  796.  TSeqPos uLength)
  797. {
  798.     return x_GetImplementation().Pack
  799.         (in_seq, uLength);
  800. }
  801. bool CSeqportUtil::FastValidate
  802. (const CSeq_data&   in_seq,
  803.  TSeqPos            uBeginIdx,
  804.  TSeqPos            uLength)
  805. {
  806.     return x_GetImplementation().FastValidate
  807.         (in_seq, uBeginIdx, uLength);
  808. }
  809. void CSeqportUtil::Validate
  810. (const CSeq_data&   in_seq,
  811.  vector<TSeqPos>*   badIdx,
  812.  TSeqPos            uBeginIdx,
  813.  TSeqPos            uLength)
  814. {
  815.     x_GetImplementation().Validate
  816.         (in_seq, badIdx, uBeginIdx, uLength);
  817. }
  818. TSeqPos CSeqportUtil::GetAmbigs
  819. (const CSeq_data&     in_seq,
  820.  CSeq_data*           out_seq,
  821.  vector<TSeqPos>*     out_indices,
  822.  CSeq_data::E_Choice  to_code,
  823.  TSeqPos              uBeginIdx,
  824.  TSeqPos              uLength)
  825. {
  826.     return x_GetImplementation().GetAmbigs
  827.         (in_seq, out_seq, out_indices, to_code, uBeginIdx, uLength);
  828. }
  829. TSeqPos CSeqportUtil::GetCopy
  830. (const CSeq_data&   in_seq,
  831.  CSeq_data*         out_seq,
  832.  TSeqPos            uBeginIdx,
  833.  TSeqPos            uLength)
  834. {
  835.     return x_GetImplementation().GetCopy
  836.         (in_seq, out_seq, uBeginIdx, uLength);
  837. }
  838. TSeqPos CSeqportUtil::Keep
  839. (CSeq_data*   in_seq,
  840.  TSeqPos      uBeginIdx,
  841.  TSeqPos      uLength)
  842. {
  843.     return x_GetImplementation().Keep
  844.         (in_seq, uBeginIdx, uLength);
  845. }
  846. TSeqPos CSeqportUtil::Append
  847. (CSeq_data*         out_seq,
  848.  const CSeq_data&   in_seq1,
  849.  TSeqPos            uBeginIdx1,
  850.  TSeqPos            uLength1,
  851.  const CSeq_data&   in_seq2,
  852.  TSeqPos            uBeginIdx2,
  853.  TSeqPos            uLength2)
  854. {
  855.     return x_GetImplementation().Append
  856.         (out_seq,
  857.          in_seq1, uBeginIdx1, uLength1, in_seq2, uBeginIdx2, uLength2);
  858. }
  859. TSeqPos CSeqportUtil::Complement
  860. (CSeq_data*   in_seq,
  861.  TSeqPos      uBeginIdx,
  862.  TSeqPos      uLength)
  863. {
  864.     return x_GetImplementation().Complement
  865.         (in_seq, uBeginIdx, uLength);
  866. }
  867. TSeqPos CSeqportUtil::Complement
  868. (const CSeq_data&   in_seq,
  869.  CSeq_data*         out_seq,
  870.  TSeqPos            uBeginIdx,
  871.  TSeqPos            uLength)
  872. {
  873.     return x_GetImplementation().Complement
  874.         (in_seq, out_seq, uBeginIdx, uLength);
  875. }
  876. TSeqPos CSeqportUtil::Reverse
  877. (CSeq_data*   in_seq,
  878.  TSeqPos      uBeginIdx,
  879.  TSeqPos      uLength)
  880. {
  881.     return x_GetImplementation().Reverse
  882.         (in_seq, uBeginIdx, uLength);
  883. }
  884. TSeqPos CSeqportUtil::Reverse
  885. (const CSeq_data&  in_seq,
  886.  CSeq_data*        out_seq,
  887.  TSeqPos           uBeginIdx,
  888.  TSeqPos           uLength)
  889. {
  890.     return x_GetImplementation().Reverse
  891.         (in_seq, out_seq, uBeginIdx, uLength);
  892. }
  893. TSeqPos CSeqportUtil::ReverseComplement
  894. (CSeq_data*  in_seq,
  895.  TSeqPos     uBeginIdx,
  896.  TSeqPos     uLength)
  897. {
  898.     return x_GetImplementation().ReverseComplement
  899.         (in_seq, uBeginIdx, uLength);
  900. }
  901. TSeqPos CSeqportUtil::ReverseComplement
  902. (const CSeq_data&  in_seq,
  903.  CSeq_data*        out_seq,
  904.  TSeqPos           uBeginIdx,
  905.  TSeqPos           uLength)
  906. {
  907.     return x_GetImplementation().ReverseComplement
  908.         (in_seq, out_seq, uBeginIdx, uLength);
  909. }
  910. const string& CSeqportUtil::GetIupacaa3(TIndex ncbistdaa)
  911. {
  912.     return x_GetImplementation().GetIupacaa3(ncbistdaa);
  913. }
  914. bool CSeqportUtil::IsCodeAvailable(CSeq_data::E_Choice code_type)
  915. {
  916.     return x_GetImplementation().IsCodeAvailable(code_type);
  917. }
  918. bool CSeqportUtil::IsCodeAvailable(ESeq_code_type code_type)
  919. {
  920.     return x_GetImplementation().IsCodeAvailable(code_type);
  921. }
  922. CSeqportUtil::TPair CSeqportUtil::GetCodeIndexFromTo
  923. (CSeq_data::E_Choice code_type)
  924. {
  925.     return x_GetImplementation().GetCodeIndexFromTo(code_type);
  926. }
  927. CSeqportUtil::TPair CSeqportUtil::GetCodeIndexFromTo
  928. (ESeq_code_type code_type)
  929. {
  930.     return x_GetImplementation().GetCodeIndexFromTo(code_type);
  931. }
  932. const string& CSeqportUtil::GetCode
  933. (CSeq_data::E_Choice code_type, 
  934.  TIndex              idx) 
  935. {
  936.     return x_GetImplementation().GetCodeOrName(code_type, idx, true);
  937. }
  938. const string& CSeqportUtil::GetCode
  939. (ESeq_code_type code_type, 
  940.  TIndex         idx) 
  941. {
  942.     return x_GetImplementation().GetCodeOrName(code_type, idx, true);
  943. }
  944. const string& CSeqportUtil::GetName
  945. (CSeq_data::E_Choice code_type, 
  946.  TIndex              idx) 
  947. {
  948.     return x_GetImplementation().GetCodeOrName(code_type, idx, false);
  949. }
  950. const string& CSeqportUtil::GetName
  951. (ESeq_code_type code_type, 
  952.  TIndex         idx) 
  953. {
  954.     return x_GetImplementation().GetCodeOrName(code_type, idx, false);
  955. }
  956. CSeqportUtil::TIndex CSeqportUtil::GetIndex
  957. (CSeq_data::E_Choice code_type,
  958.  const string&       code)
  959. {
  960.     return x_GetImplementation().GetIndex(code_type, code);
  961. }
  962. CSeqportUtil::TIndex CSeqportUtil::GetIndex
  963. (ESeq_code_type code_type,
  964.  const string&  code)
  965. {
  966.     return x_GetImplementation().GetIndex(code_type, code);
  967. }
  968. CSeqportUtil::TIndex CSeqportUtil::GetIndexComplement
  969. (CSeq_data::E_Choice code_type,
  970.  TIndex        idx)
  971. {
  972.     return x_GetImplementation().GetIndexComplement(code_type, idx);
  973. }
  974. CSeqportUtil::TIndex CSeqportUtil::GetIndexComplement
  975. (ESeq_code_type code_type,
  976.  TIndex         idx)
  977. {
  978.     return x_GetImplementation().GetIndexComplement(code_type, idx);
  979. }
  980. CSeqportUtil::TIndex CSeqportUtil::GetMapToIndex
  981. (CSeq_data::E_Choice from_type,
  982.  CSeq_data::E_Choice to_type,
  983.  TIndex              from_idx)
  984. {
  985.     return x_GetImplementation().GetMapToIndex(from_type, to_type, from_idx);
  986. }
  987. CSeqportUtil::TIndex CSeqportUtil::GetMapToIndex
  988. (ESeq_code_type from_type,
  989.  ESeq_code_type to_type,
  990.  TIndex         from_idx)
  991. {
  992.     return x_GetImplementation().GetMapToIndex(from_type, to_type, from_idx);
  993. }
  994. CSeqportUtil_implementation::CSeqportUtil_implementation()
  995. {
  996.     // Initialize m_SeqCodeSet
  997.     m_SeqCodeSet = Init();
  998.     // Initialize code tables
  999.     m_Iupacna = InitCodes(eSeq_code_type_iupacna);
  1000.     m_Ncbieaa = InitCodes(eSeq_code_type_ncbieaa);
  1001.     m_Ncbistdaa = InitCodes(eSeq_code_type_ncbistdaa);
  1002.     m_Iupacaa = InitCodes(eSeq_code_type_iupacaa);
  1003.     // Initialize na complement tables
  1004.     m_Iupacna_complement = InitIupacnaComplement();
  1005.     m_Ncbi2naComplement = InitNcbi2naComplement();
  1006.     m_Ncbi4naComplement = InitNcbi4naComplement();
  1007.     // Initialize na reverse tables
  1008.     m_Ncbi2naRev = InitNcbi2naRev();
  1009.     m_Ncbi4naRev = InitNcbi4naRev();
  1010.     // Initialize map tables
  1011.     m_Ncbi2naIupacna = InitMaps(eSeq_code_type_ncbi2na,
  1012.                                 eSeq_code_type_iupacna);
  1013.     m_Ncbi2naNcbi4na = InitMaps(eSeq_code_type_ncbi2na,
  1014.                                 eSeq_code_type_ncbi4na);
  1015.     m_Ncbi4naIupacna = InitMaps(eSeq_code_type_ncbi4na,
  1016.                                 eSeq_code_type_iupacna);
  1017.     m_IupacnaNcbi2na = InitMaps(eSeq_code_type_iupacna,
  1018.                                 eSeq_code_type_ncbi2na);
  1019.     m_IupacnaNcbi4na = InitMaps(eSeq_code_type_iupacna,
  1020.                                 eSeq_code_type_ncbi4na);
  1021.     m_Ncbi4naNcbi2na = InitMaps(eSeq_code_type_ncbi4na,
  1022.                                 eSeq_code_type_ncbi2na);
  1023.     m_IupacaaNcbieaa = InitMaps(eSeq_code_type_iupacaa,
  1024.                                 eSeq_code_type_ncbieaa);
  1025.     m_NcbieaaIupacaa = InitMaps(eSeq_code_type_ncbieaa,
  1026.                                 eSeq_code_type_iupacaa);
  1027.     m_IupacaaNcbistdaa = InitMaps(eSeq_code_type_iupacaa,
  1028.                                   eSeq_code_type_ncbistdaa);
  1029.     m_NcbieaaNcbistdaa = InitMaps(eSeq_code_type_ncbieaa,
  1030.                                   eSeq_code_type_ncbistdaa);
  1031.     m_NcbistdaaNcbieaa = InitMaps(eSeq_code_type_ncbistdaa,
  1032.                                   eSeq_code_type_ncbieaa);
  1033.     m_NcbistdaaIupacaa = InitMaps(eSeq_code_type_ncbistdaa,
  1034.                                   eSeq_code_type_iupacaa);
  1035.     // Initialize fast conversion tables
  1036.     //m_FastNcbi2naIupacna = InitFastNcbi2naIupacna();
  1037.     //m_FastNcbi2naNcbi4na = InitFastNcbi2naNcbi4na();
  1038.     //m_FastNcbi4naIupacna = InitFastNcbi4naIupacna();
  1039.     m_FastIupacnaNcbi2na = InitFastIupacnaNcbi2na();
  1040.     m_FastIupacnaNcbi4na = InitFastIupacnaNcbi4na();
  1041.     m_FastNcbi4naNcbi2na = InitFastNcbi4naNcbi2na();
  1042.     
  1043.     // Initialize tables for conversion of index to codes or names
  1044.     InitIndexCodeName();
  1045.     // Initialize m_Masks used for random ambiguity resolution
  1046.     m_Masks = CSeqportUtil_implementation::InitMasks();
  1047.     // Initialize m_DetectAmbigNcbi4naNcbi2na used for ambiguity
  1048.     // detection and reporting
  1049.     m_DetectAmbigNcbi4naNcbi2na = InitAmbigNcbi4naNcbi2na();
  1050.     // Initialize m_DetectAmbigIupacnaNcbi2na used for ambiguity detection
  1051.     // and reporting
  1052.     m_DetectAmbigIupacnaNcbi2na = InitAmbigIupacnaNcbi2na();
  1053. }
  1054. // Destructor. All memory allocated on the
  1055. // free store is wrapped in smart pointers.
  1056. // Therefore, the destructor does not need
  1057. // to deallocate memory.
  1058. CSeqportUtil_implementation::~CSeqportUtil_implementation()
  1059. {
  1060.     return;
  1061. }
  1062. /////////////////////////////////////////////////////////////////////////////
  1063. //  PRIVATE::
  1064. //
  1065. // Helper function to initialize m_SeqCodeSet from sm_StrAsnData
  1066. CRef<CSeq_code_set> CSeqportUtil_implementation::Init()
  1067. {
  1068.     // Compose a long-long string
  1069.     string str;
  1070.     for (size_t i = 0;  sm_StrAsnData[i];  i++) {
  1071.         str += sm_StrAsnData[i];
  1072.     }
  1073.     // Create an in memory stream on sm_StrAsnData
  1074.     CNcbiIstrstream is(str.c_str(), str.length());
  1075.     auto_ptr<CObjectIStream>
  1076.         asn_codes_in(CObjectIStream::Open(eSerial_AsnText, is));
  1077.     // Create a CSeq_code_set
  1078.     CRef<CSeq_code_set> ptr_seq_code_set(new CSeq_code_set());
  1079.     // Initialize the newly created CSeq_code_set
  1080.     *asn_codes_in >> *ptr_seq_code_set;
  1081.     // Return a newly created CSeq_code_set
  1082.     return ptr_seq_code_set;
  1083. }
  1084. // Function to initialize code tables
  1085. CRef<CSeqportUtil_implementation::CCode_table>
  1086. CSeqportUtil_implementation::InitCodes(ESeq_code_type code_type)
  1087. {
  1088.     // Get list of code tables
  1089.     const list<CRef<CSeq_code_table> >& code_list = m_SeqCodeSet->GetCodes();
  1090.     // Get table for code_type
  1091.     list<CRef<CSeq_code_table> >::const_iterator i_ct;
  1092.     for(i_ct = code_list.begin(); i_ct != code_list.end(); ++i_ct)
  1093.         if((*i_ct)->GetCode() == code_type)
  1094.             break;
  1095.     if(i_ct == code_list.end())
  1096.         throw runtime_error("Requested code table not found");
  1097.     // Get table data
  1098.     const list<CRef<CSeq_code_table::C_E> >& table_data = (*i_ct)->GetTable();
  1099.     SIZE_TYPE size = table_data.size();
  1100.     int start_at = (*i_ct)->GetStart_at();
  1101.     CRef<CCode_table> codeTable(new CCode_table(size, start_at));
  1102.     // Initialize codeTable to 255
  1103.     for(int i=0; i<256; i++)
  1104.         codeTable->m_Table[i] = 'xff';
  1105.     // Copy table data to codeTable
  1106.     int nIdx = start_at;
  1107.     list<CRef<CSeq_code_table::C_E> >::const_iterator i_td;
  1108.     for(i_td = table_data.begin(); i_td != table_data.end(); ++i_td) {
  1109.         codeTable->m_Table[nIdx] =  *((*i_td)->GetSymbol().c_str());
  1110.         if(codeTable->m_Table[nIdx] == 'x00')
  1111.             codeTable->m_Table[nIdx++] = 'xff';
  1112.         else
  1113.             nIdx++;
  1114.     }
  1115.     // Return codeTable
  1116.     return codeTable;
  1117. }
  1118. // Function to initialize iupacna complement table
  1119. CRef<CSeqportUtil_implementation::CCode_comp>
  1120. CSeqportUtil_implementation::InitIupacnaComplement()
  1121. {
  1122.     // Get list of code tables
  1123.     const list<CRef<CSeq_code_table> >& code_list = m_SeqCodeSet->GetCodes();
  1124.     // Get table for code_type iupacna
  1125.     list<CRef<CSeq_code_table> >::const_iterator i_ct;
  1126.     for(i_ct = code_list.begin(); i_ct != code_list.end(); ++i_ct)
  1127.         if((*i_ct)->GetCode() == eSeq_code_type_iupacna)
  1128.             break;
  1129.     if(i_ct == code_list.end())
  1130.         throw runtime_error("Code table for Iupacna not found");
  1131.     // Check that complements are set
  1132.     if(!(*i_ct)->IsSetComps())
  1133.         throw runtime_error("Complement data is not set for iupacna table");
  1134.     // Get complement data, start at and size of complement data
  1135.     const list<int>& comp_data = (*i_ct)->GetComps();
  1136.     int start_at = (*i_ct)->GetStart_at();
  1137.     // Allocate memory for complement data
  1138.     CRef<CCode_comp> compTable(new CCode_comp(256, start_at));
  1139.     // Initialize compTable to 255 for illegal codes
  1140.     for(unsigned int i = 0; i<256; i++)
  1141.         compTable->m_Table[i] = (char) 255;
  1142.     // Loop trhough the complement data and set compTable
  1143.     list<int>::const_iterator i_comp;
  1144.     unsigned int nIdx = start_at;
  1145.     for(i_comp = comp_data.begin(); i_comp != comp_data.end(); ++i_comp)
  1146.         compTable->m_Table[nIdx++] = (*i_comp);
  1147.     // Return the complement data
  1148.     return compTable;
  1149. }
  1150. // Function to initialize ncbi2na complement table
  1151. CRef<CSeqportUtil_implementation::CCode_comp>
  1152. CSeqportUtil_implementation::InitNcbi2naComplement()
  1153. {
  1154.     // Get list of code tables
  1155.     const list<CRef<CSeq_code_table> >& code_list = m_SeqCodeSet->GetCodes();
  1156.     // Get table for code_type ncbi2na
  1157.     list<CRef<CSeq_code_table> >::const_iterator i_ct;
  1158.     for(i_ct = code_list.begin(); i_ct != code_list.end(); ++i_ct)
  1159.         if((*i_ct)->GetCode() == eSeq_code_type_ncbi2na)
  1160.             break;
  1161.     if(i_ct == code_list.end())
  1162.         throw runtime_error("Code table for Iupacna not found");
  1163.     // Check that complements are set
  1164.     if(!(*i_ct)->IsSetComps())
  1165.         throw runtime_error("Complement data is not set for ncbi2na table");
  1166.     // Get complement data, start at and size of complement data
  1167.     const list<int>& comp_data = (*i_ct)->GetComps();
  1168.     int start_at = (*i_ct)->GetStart_at();
  1169.     // Allocate memory for complement data
  1170.     CRef<CCode_comp> compTable(new CCode_comp(256, start_at));
  1171.     // Put complement data in an array
  1172.     char compArray[4];
  1173.     int nIdx = start_at;
  1174.     list<int>::const_iterator i_comp;
  1175.     for(i_comp = comp_data.begin(); i_comp != comp_data.end(); ++i_comp)
  1176.         compArray[nIdx++] = (*i_comp);
  1177.     // Set compTable
  1178.     for(unsigned int i = 0; i < 4; i++)
  1179.         for(unsigned int j = 0; j < 4; j++)
  1180.             for(unsigned int k = 0; k < 4; k++)
  1181.                 for(unsigned int l = 0; l < 4; l++)
  1182.                     {
  1183.                         nIdx = i<<6 | j<<4 | k<<2 | l;
  1184.                         char c1 = compArray[i] << 6;
  1185.                         char c2 = compArray[j] << 4;
  1186.                         char c3 = compArray[k] << 2;
  1187.                         char c4 = compArray[l];
  1188.                         compTable->m_Table[nIdx] = c1 | c2 | c3 | c4;
  1189.                     }
  1190.     // Return complement data
  1191.     return compTable;
  1192. }
  1193. // Function to initialize ncbi4na complement table
  1194. CRef<CSeqportUtil_implementation::CCode_comp>
  1195. CSeqportUtil_implementation::InitNcbi4naComplement()
  1196. {
  1197.     // Get list of code tables
  1198.     const list<CRef<CSeq_code_table> >& code_list = m_SeqCodeSet->GetCodes();
  1199.     // Get table for code_type ncbi2na
  1200.     list<CRef<CSeq_code_table> >::const_iterator i_ct;
  1201.     for(i_ct = code_list.begin(); i_ct != code_list.end(); ++i_ct)
  1202.         if((*i_ct)->GetCode() == eSeq_code_type_ncbi4na)
  1203.             break;
  1204.     if(i_ct == code_list.end())
  1205.         throw runtime_error("Code table for Iupacna not found");
  1206.     // Check that complements are set
  1207.     if(!(*i_ct)->IsSetComps())
  1208.         throw runtime_error("Complement data is not set for iupacna table");
  1209.     // Get complement data, start at and size of complement data
  1210.     const list<int>& comp_data = (*i_ct)->GetComps();
  1211.     int start_at = (*i_ct)->GetStart_at();
  1212.     // Allocate memory for complement data
  1213.     CRef<CCode_comp> compTable(new CCode_comp(256, start_at));
  1214.     // Put complement data in an array
  1215.     char compArray[16];
  1216.     int nIdx = start_at;
  1217.     list<int>::const_iterator i_comp;
  1218.     for(i_comp = comp_data.begin(); i_comp != comp_data.end(); ++i_comp)
  1219.         compArray[nIdx++] = (*i_comp);
  1220.     // Set compTable
  1221.     for(unsigned int i = 0; i<16; i++)
  1222.         for(unsigned int j = 0; j < 16; j++)
  1223.             {
  1224.                 nIdx = i<<4 | j;
  1225.                 char c1 = compArray[i] << 4;
  1226.                 char c2 = compArray[j];
  1227.                 compTable->m_Table[nIdx] = c1 | c2;
  1228.             }
  1229.     // Return complement data
  1230.     return compTable;
  1231. }
  1232. // Function to initialize m_Ncbi2naRev
  1233. CRef<CSeqportUtil_implementation::CCode_rev> CSeqportUtil_implementation::InitNcbi2naRev()
  1234. {
  1235.     // Allocate memory for reverse table
  1236.     CRef<CCode_rev> revTable(new CCode_rev(256, 0));
  1237.     // Initialize table used to reverse a byte.
  1238.     for(unsigned int i = 0; i < 4; i++)
  1239.         for(unsigned int j = 0; j < 4; j++)
  1240.             for(unsigned int k = 0; k < 4; k++)
  1241.                 for(unsigned int l = 0; l < 4; l++)
  1242.                     revTable->m_Table[64*i + 16*j + 4*k + l] =
  1243.                         64*l + 16*k + 4*j +i;
  1244.     // Return the reverse table
  1245.     return revTable;
  1246. }
  1247. // Function to initialize m_Ncbi4naRev
  1248. CRef<CSeqportUtil_implementation::CCode_rev> CSeqportUtil_implementation::InitNcbi4naRev()
  1249. {
  1250.     // Allocate memory for reverse table
  1251.     CRef<CCode_rev> revTable(new CCode_rev(256, 0));
  1252.     // Initialize table used to reverse a byte.
  1253.     for(unsigned int i = 0; i < 16; i++)
  1254.         for(unsigned int j = 0; j < 16; j++)
  1255.             revTable->m_Table[16*i + j] = 16*j + i;
  1256.     // Return the reverse table
  1257.     return revTable;
  1258. }
  1259. // Function to initialize map tables
  1260. CRef<CSeqportUtil_implementation::CMap_table> 
  1261. CSeqportUtil_implementation::InitMaps
  1262. (ESeq_code_type from_type,
  1263.  ESeq_code_type to_type)
  1264. {
  1265.     // Get list of map tables
  1266.     const list< CRef< CSeq_map_table > >& map_list = m_SeqCodeSet->GetMaps();
  1267.     // Get requested map table
  1268.     list<CRef<CSeq_map_table> >::const_iterator i_mt;
  1269.     for(i_mt = map_list.begin(); i_mt != map_list.end(); ++i_mt)
  1270.         if((*i_mt)->GetFrom() == from_type && (*i_mt)->GetTo() == to_type)
  1271.             break;
  1272.     if(i_mt == map_list.end())
  1273.         throw runtime_error("Requested map table not found");
  1274.     // Get the map table
  1275.     const list<int>& table_data = (*i_mt)->GetTable();
  1276.     // Create a map table reference
  1277.     SIZE_TYPE size = table_data.size();
  1278.     int start_at = (*i_mt)->GetStart_at();
  1279.     CRef<CMap_table> mapTable(new CMap_table(size,start_at));
  1280.     // Copy the table data to mapTable
  1281.     int nIdx = start_at;
  1282.     list<int>::const_iterator i_td;
  1283.     for(i_td = table_data.begin(); i_td != table_data.end(); ++i_td)
  1284.         {
  1285.             mapTable->m_Table[nIdx++] = *i_td;
  1286.         }
  1287.     return mapTable;
  1288. }
  1289. // Functions to initialize fast conversion tables
  1290. // Function to initialize FastNcib2naIupacna
  1291. /*
  1292. CRef<CSeqportUtil_implementation::CFast_table4> CSeqportUtil_implementation::InitFastNcbi2naIupacna()
  1293. {
  1294.     CRef<CFast_table4> fastTable(new CFast_table4(256,0));
  1295.     unsigned char i,j,k,l;
  1296.     for(i = 0; i < 4; i++)
  1297.         for(j = 0; j < 4; j++)
  1298.             for(k = 0; k < 4; k++)
  1299.                 for(l = 0; l < 4; l++)
  1300.                     {
  1301.                         unsigned char aByte = (i<<6) | (j<<4) | (k<<2) | l;
  1302.                         char chi = m_Ncbi2naIupacna->m_Table[i];
  1303.                         char chj = m_Ncbi2naIupacna->m_Table[j];
  1304.                         char chk = m_Ncbi2naIupacna->m_Table[k];
  1305.                         char chl = m_Ncbi2naIupacna->m_Table[l];
  1306.                         // Note high order bit pair corresponds to low order
  1307.                         // byte etc., on Unix machines.
  1308.                         char *pt = 
  1309.                             reinterpret_cast<char*>(&fastTable->m_Table[aByte]);
  1310.                         *(pt++) = chi;
  1311.                         *(pt++) = chj;
  1312.                         *(pt++) = chk;
  1313.                         *(pt) = chl;                       
  1314.                      }
  1315.     return fastTable;
  1316. }
  1317. */
  1318. // Function to initialize FastNcib2naNcbi4na
  1319. CRef<CSeqportUtil_implementation::CFast_table2> CSeqportUtil_implementation::InitFastNcbi2naNcbi4na()
  1320. {
  1321.     CRef<CFast_table2> fastTable(new CFast_table2(256,0));
  1322.     unsigned char i, j, k, l;
  1323.     for(i = 0; i < 4; i++)
  1324.         for(j = 0; j < 4; j++)
  1325.             for(k = 0; k < 4; k++)
  1326.                 for(l = 0; l < 4; l++) {
  1327.                     unsigned char aByte = (i<<6) | (j<<4) | (k<<2) | l;
  1328.                     unsigned char chi = m_Ncbi2naNcbi4na->m_Table[i];
  1329.                     unsigned char chj = m_Ncbi2naNcbi4na->m_Table[j];
  1330.                     unsigned char chk = m_Ncbi2naNcbi4na->m_Table[k];
  1331.                     unsigned char chl = m_Ncbi2naNcbi4na->m_Table[l];
  1332.                     char *pt = 
  1333.                         reinterpret_cast<char*>(&fastTable->m_Table[aByte]);
  1334.                     *(pt++) = (chi << 4) | chj;
  1335.                     *pt = (chk << 4) | chl;
  1336.                 }
  1337.     return fastTable;
  1338. }
  1339. // Function to initialize FastNcib4naIupacna
  1340. CRef<CSeqportUtil_implementation::CFast_table2> CSeqportUtil_implementation::InitFastNcbi4naIupacna()
  1341. {
  1342.     CRef<CFast_table2> fastTable(new CFast_table2(256,0));
  1343.     unsigned char i,j;
  1344.     for(i = 0; i < 16; i++)
  1345.         for(j = 0; j < 16; j++) {
  1346.             unsigned char aByte = (i<<4) | j;
  1347.             unsigned char chi = m_Ncbi4naIupacna->m_Table[i];
  1348.             unsigned char chj = m_Ncbi4naIupacna->m_Table[j];
  1349.             // Note high order nible corresponds to low order byte
  1350.             // etc., on Unix machines.
  1351.             char *pt = reinterpret_cast<char*>(&fastTable->m_Table[aByte]);
  1352.             *(pt++) = chi;
  1353.             *pt = chj;
  1354.         }
  1355.     return fastTable;
  1356. }
  1357. // Function to initialize m_FastIupacnancbi2na
  1358. CRef<CSeqportUtil_implementation::CFast_4_1> CSeqportUtil_implementation::InitFastIupacnaNcbi2na()
  1359. {
  1360.     int start_at = m_IupacnaNcbi2na->m_StartAt;
  1361.     int size = m_IupacnaNcbi2na->m_Size;
  1362.     CRef<CFast_4_1> fastTable(new CFast_4_1(4,0,256,0));
  1363.     for(int ch = 0; ch < 256; ch++) {
  1364.         if((ch >= start_at) && (ch < (start_at + size)))
  1365.             {
  1366.                 unsigned char uch = m_IupacnaNcbi2na->m_Table[ch];
  1367.                 uch &= 'x03';
  1368.                 for(unsigned int pos = 0; pos < 4; pos++)
  1369.                     fastTable->m_Table[pos][ch] = uch << (6-2*pos);
  1370.             }
  1371.         else
  1372.             for(unsigned int pos = 0; pos < 4; pos++)
  1373.                 fastTable->m_Table[pos][ch] = 'x00';
  1374.     }
  1375.     return fastTable;
  1376. }
  1377. // Function to initialize m_FastIupacnancbi4na
  1378. CRef<CSeqportUtil_implementation::CFast_2_1> CSeqportUtil_implementation::InitFastIupacnaNcbi4na()
  1379. {
  1380.     int start_at = m_IupacnaNcbi4na->m_StartAt;
  1381.     int size = m_IupacnaNcbi4na->m_Size;
  1382.     CRef<CFast_2_1> fastTable(new CFast_2_1(2,0,256,0));
  1383.     for(int ch = 0; ch < 256; ch++) {
  1384.         if((ch >= start_at) && (ch < (start_at + size)))
  1385.             {
  1386.                 unsigned char uch = m_IupacnaNcbi4na->m_Table[ch];
  1387.                 for(unsigned int pos = 0; pos < 2; pos++)
  1388.                     fastTable->m_Table[pos][ch] = uch << (4-4*pos);
  1389.             }
  1390.         else
  1391.             {
  1392.                 fastTable->m_Table[0][ch] = 0xF0;
  1393.                 fastTable->m_Table[1][ch] = 0x0F;
  1394.             }
  1395.     }
  1396.     return fastTable;
  1397. }
  1398. // Function to initialize m_FastNcbi4naNcbi2na
  1399. CRef<CSeqportUtil_implementation::CFast_2_1> CSeqportUtil_implementation::InitFastNcbi4naNcbi2na()
  1400. {
  1401.     int start_at = m_Ncbi4naNcbi2na->m_StartAt;
  1402.     int size = m_Ncbi4naNcbi2na->m_Size;
  1403.     CRef<CFast_2_1> fastTable(new CFast_2_1(2,0,256,0));
  1404.     for(int n1 = 0; n1 < 16; n1++)
  1405.         for(int n2 = 0; n2 < 16; n2++) {
  1406.             int nIdx = 16*n1 + n2;
  1407.             unsigned char u1, u2;
  1408.             if((n1 >= start_at) && (n1 < start_at + size))
  1409.                 u1 = m_Ncbi4naNcbi2na->m_Table[n1] & 3;
  1410.             else
  1411.                 u1 = 'x00';
  1412.             if((n2 >= start_at) && (n2 < start_at + size))
  1413.                 u2 = m_Ncbi4naNcbi2na->m_Table[n2] & 3;
  1414.             else
  1415.                 u2 = 'x00';
  1416.             fastTable->m_Table[0][nIdx] = (u1<<6) | (u2<<4);
  1417.             fastTable->m_Table[1][nIdx] = (u1<<2) | u2;
  1418.         }
  1419.     return fastTable;
  1420. }
  1421. // Function to initialize m_IndexString and m_StringIndex
  1422. void CSeqportUtil_implementation::InitIndexCodeName()
  1423. {
  1424.     typedef list<CRef<CSeq_code_table> >      Ttables;
  1425.     typedef list<CRef<CSeq_code_table::C_E> > Tcodes;
  1426.     
  1427.     m_IndexString[kName].resize(kNumCodes);
  1428.     m_IndexString[kSymbol].resize(kNumCodes);
  1429.     m_IndexComplement.resize(kNumCodes);
  1430.     m_StringIndex.resize(kNumCodes);
  1431.     m_StartAt.resize(kNumCodes);
  1432.     bool found[kNumCodes];
  1433.     for (unsigned int ii = 0; ii < kNumCodes; ii++) {
  1434.         found[ii] = false;
  1435.     }
  1436.     ITERATE (Ttables, it, m_SeqCodeSet->GetCodes()) {
  1437.         const ESeq_code_type& code = (*it)->GetCode();
  1438.         if (!found[code-1]) {
  1439.             found[code-1] = true;
  1440.             m_StartAt[code-1] = (*it)->IsSetStart_at() ?
  1441.                 (*it)->GetStart_at() : 0;
  1442.             TIndex i = m_StartAt[code-1];
  1443.             ITERATE(Tcodes, is, (*it)->GetTable()) {                
  1444.                 m_IndexString[kSymbol][code-1].push_back((*is)->GetSymbol());
  1445.                 m_IndexString[kName][code-1].push_back((*is)->GetName());
  1446.                 m_StringIndex[code-1].insert
  1447.                     (make_pair((*is)->GetSymbol(), i++));
  1448.             }
  1449.             if ( (*it)->IsSetComps() ) {
  1450.                 ITERATE (list<int>, ic, (*it)->GetComps()) {
  1451.                     m_IndexComplement[code-1].push_back(*ic);
  1452.                 }
  1453.             }
  1454.         }
  1455.     }
  1456.     
  1457.      
  1458. }
  1459. // Function to initialize m_Masks
  1460. CRef<CSeqportUtil_implementation::SMasksArray> CSeqportUtil_implementation::InitMasks()
  1461. {
  1462.     unsigned int i, j, uCnt;
  1463.     unsigned char cVal, cRslt;
  1464.     CRef<SMasksArray> aMask(new SMasksArray);
  1465.     // Initialize possible masks for converting ambiguous
  1466.     // ncbi4na bytes to unambiguous bytes
  1467.     static const unsigned char mask[16] = {
  1468.         0x11, 0x12, 0x14, 0x18,
  1469.         0x21, 0x22, 0x24, 0x28,
  1470.         0x41, 0x42, 0x44, 0x48,
  1471.         0x81, 0x82, 0x84, 0x88
  1472.     };
  1473.     static const unsigned char maskUpper[4] = { 0x10, 0x20, 0x40, 0x80 };
  1474.     static const unsigned char maskLower[4] = { 0x01, 0x02, 0x04, 0x08 };
  1475.     // Loop through possible ncbi4na bytes and
  1476.     // build masks that convert it to unambiguous na
  1477.     for(i = 0; i < 256; i++) {
  1478.         cVal = i;
  1479.         uCnt = 0;
  1480.         // Case where both upper and lower nible > 0
  1481.         if(((cVal & 'x0f') != 0) && ((cVal & 'xf0') != 0))
  1482.             for(j = 0; j < 16; j++) {
  1483.                 cRslt = cVal & mask[j];
  1484.                 if(cRslt == mask[j])
  1485.                     aMask->m_Table[i].cMask[uCnt++] = mask[j];
  1486.             }
  1487.         // Case where upper nible = 0 and lower nible > 0
  1488.         else if((cVal & 'x0f') != 0)
  1489.             for(j = 0; j < 4; j++)
  1490.                 {
  1491.                     cRslt = cVal & maskLower[j];
  1492.                     if(cRslt == maskLower[j])
  1493.                         aMask->m_Table[i].cMask[uCnt++] = maskLower[j];
  1494.                 }
  1495.         // Case where lower nible = 0 and upper nible > 0
  1496.         else if((cVal & 'xf0') != 0)
  1497.             for(j = 0; j < 4; j++)
  1498.                 {
  1499.                     cRslt = cVal & maskUpper[j];
  1500.                     if(cRslt == maskUpper[j])
  1501.                         aMask->m_Table[i].cMask[uCnt++] = maskUpper[j];
  1502.                 }
  1503.         // Both upper and lower nibles = 0
  1504.         else
  1505.             aMask->m_Table[i].cMask[uCnt++] = 'x00';
  1506.         // Number of distict masks for ncbi4na byte i
  1507.         aMask->m_Table[i].nMasks = uCnt;
  1508.         // Fill out the remainder of cMask array with copies
  1509.         // of first uCnt masks
  1510.         for(j = uCnt; j < 16 && uCnt > 0; j++)
  1511.             aMask->m_Table[i].cMask[j] = aMask->m_Table[i].cMask[j % uCnt];
  1512.     }
  1513.     return aMask;
  1514. }
  1515. // Function to initialize m_DetectAmbigNcbi4naNcbi2na used for
  1516. // ambiguity detection
  1517. CRef<CSeqportUtil_implementation::CAmbig_detect> CSeqportUtil_implementation::InitAmbigNcbi4naNcbi2na()
  1518. {
  1519.     unsigned char low, high, ambig;
  1520.     // Create am new CAmbig_detect object
  1521.     CRef<CAmbig_detect> ambig_detect(new CAmbig_detect(256,0));
  1522.     // Loop through low and high order nibles and assign
  1523.     // values as follows: 0 - no ambiguity, 1 - low order nible ambigiguous
  1524.     // 2 - high order ambiguous, 3 -- both high and low ambiguous.
  1525.     // Loop for low order nible
  1526.     for(low = 0; low < 16; low++) {
  1527.         // Determine if low order nible is ambiguous
  1528.         if((low == 1) || (low ==2) || (low == 4) || (low == 8))
  1529.             ambig = 0;  // Not ambiguous
  1530.         else
  1531.             ambig = 1;  // Ambiguous
  1532.         // Loop for high order nible
  1533.         for(high = 0; high < 16; high++) {
  1534.             // Determine if high order nible is ambiguous
  1535.             if((high != 1) && (high != 2) && (high != 4) && (high != 8))
  1536.                 ambig += 2;  // Ambiguous
  1537.             // Set ambiguity value
  1538.             ambig_detect->m_Table[16*high + low] = ambig;
  1539.             // Reset ambig
  1540.             ambig &= 'xfd';  // Set second bit to 0
  1541.         }
  1542.     }
  1543.     return ambig_detect;
  1544. }
  1545. // Function to initialize m_DetectAmbigIupacnaNcbi2na used for ambiguity
  1546. // detection
  1547. CRef<CSeqportUtil_implementation::CAmbig_detect> CSeqportUtil_implementation::InitAmbigIupacnaNcbi2na()
  1548. {
  1549.     // Create am new CAmbig_detect object
  1550.     CRef<CAmbig_detect> ambig_detect(new CAmbig_detect(256,0));
  1551.     // 0 implies no ambiguity. 1 implies ambiguity
  1552.     // Initialize to 0
  1553.     for(unsigned int i = 0; i<256; i++)
  1554.         ambig_detect->m_Table[i] = 0;
  1555.     // Set iupacna characters that are ambiguous when converted
  1556.     // to ncib2na
  1557.     ambig_detect->m_Table[66] = 1; // B
  1558.     ambig_detect->m_Table[68] = 1; // D
  1559.     ambig_detect->m_Table[72] = 1; // H
  1560.     ambig_detect->m_Table[75] = 1; // K
  1561.     ambig_detect->m_Table[77] = 1; // M
  1562.     ambig_detect->m_Table[78] = 1; // N
  1563.     ambig_detect->m_Table[82] = 1; // R
  1564.     ambig_detect->m_Table[83] = 1; // S
  1565.     ambig_detect->m_Table[86] = 1; // V
  1566.     ambig_detect->m_Table[87] = 1; // W
  1567.     ambig_detect->m_Table[89] = 1; // Y
  1568.     return ambig_detect;
  1569. }
  1570. /*
  1571. struct SSeqDataToSeqUtil
  1572. {
  1573.     CSeq_data::E_Choice  seq_data_coding;
  1574.     CSeqConvert::TCoding seq_convert_coding;
  1575. };
  1576. static SSeqDataToSeqUtil s_SeqDataToSeqUtilMap[] = {
  1577.     { CSeq_data::e_Iupacna,   CSeqUtil::e_Iupacna },
  1578.     { CSeq_data::e_Iupacaa,   CSeqUtil::e_Iupacna },
  1579.     { CSeq_data::e_Ncbi2na,   CSeqUtil::e_Ncbi2na },
  1580.     { CSeq_data::e_Ncbi4na,   CSeqUtil::e_Ncbi4na },
  1581.     { CSeq_data::e_Ncbi8na,   CSeqUtil::e_Ncbi8na },
  1582.     { CSeq_data::e_Ncbi8aa,   CSeqUtil::e_Ncbi8aa },
  1583.     { CSeq_data::e_Ncbieaa,   CSeqUtil::e_Ncbieaa },
  1584.     { CSeq_data::e_Ncbistdaa, CSeqUtil::e_Ncbistdaa }
  1585. };
  1586. */
  1587. static CSeqUtil::TCoding s_SeqDataToSeqUtil[] = {
  1588.     CSeqUtil::e_not_set,
  1589.     CSeqUtil::e_Iupacna,
  1590.     CSeqUtil::e_Iupacaa,
  1591.     CSeqUtil::e_Ncbi2na,
  1592.     CSeqUtil::e_Ncbi4na,
  1593.     CSeqUtil::e_Ncbi8na,
  1594.     CSeqUtil::e_not_set,
  1595.     CSeqUtil::e_Ncbi8aa,
  1596.     CSeqUtil::e_Ncbieaa,
  1597.     CSeqUtil::e_not_set,
  1598.     CSeqUtil::e_Ncbistdaa
  1599. };
  1600. // Convert from one coding scheme to another. The following
  1601. // 12 conversions are supported: ncbi2na<=>ncbi4na;
  1602. // ncbi2na<=>iupacna; ncbi4na<=>iupacna; ncbieaa<=>ncbistdaa;
  1603. // ncbieaa<=>iupacaa; ncbistdaa<=>iupacaa. Convert is
  1604. // really just a dispatch function--it calls the appropriate
  1605. // priviate conversion function.
  1606. TSeqPos CSeqportUtil_implementation::x_ConvertAmbig
  1607. (const CSeq_data&      in_seq,
  1608.  CSeq_data*            out_seq,
  1609.  CSeq_data::E_Choice   to_code,
  1610.  TSeqPos               uBeginIdx,
  1611.  TSeqPos               uLength,
  1612.  CRandom::TValue       seed)
  1613.     const
  1614. {
  1615.     CSeq_data::E_Choice from_code = in_seq.Which();
  1616.     if(to_code == CSeq_data::e_not_set || from_code == CSeq_data::e_not_set)
  1617.         throw std::runtime_error("to_code or from_code not set");
  1618.     if ( to_code != CSeq_data::e_Ncbi2na ) {
  1619.         throw std::runtime_error("to_code is not Ncbi2na");
  1620.     }
  1621.     switch (from_code) {
  1622.     case CSeq_data::e_Iupacna:
  1623.         return MapIupacnaToNcbi2na(in_seq, out_seq,
  1624.             uBeginIdx, uLength, true, seed);
  1625.     case CSeq_data::e_Ncbi4na:
  1626.         return MapNcbi4naToNcbi2na(in_seq, out_seq,
  1627.             uBeginIdx, uLength, true, seed);
  1628.     default:
  1629.         throw runtime_error("Requested conversion not implemented");
  1630.     }
  1631. }
  1632. // Convert from one coding scheme to another. The following
  1633. // 12 conversions are supported: ncbi2na<=>ncbi4na;
  1634. // ncbi2na<=>iupacna; ncbi4na<=>iupacna; ncbieaa<=>ncbistdaa;
  1635. // ncbieaa<=>iupacaa; ncbistdaa<=>iupacaa. Convert is
  1636. // really just a dispatch function--it calls the appropriate
  1637. // priviate conversion function.
  1638. TSeqPos CSeqportUtil_implementation::Convert
  1639. (const CSeq_data&      in_seq,
  1640.  CSeq_data*            out_seq,
  1641.  CSeq_data::E_Choice   to_code,
  1642.  TSeqPos               uBeginIdx,
  1643.  TSeqPos               uLength,
  1644.  bool                  bAmbig,
  1645.  CRandom::TValue       seed)
  1646.     const
  1647. {
  1648.     CSeq_data::E_Choice from_code = in_seq.Which();
  1649.     // adjust uLength
  1650.     if ( uLength == 0 ) {
  1651.         uLength = numeric_limits<TSeqPos>::max();
  1652.     }
  1653.     if(to_code == CSeq_data::e_not_set || from_code == CSeq_data::e_not_set) {
  1654.         throw std::runtime_error("to_code or from_code not set");
  1655.     }
  1656.     if ( s_SeqDataToSeqUtil[to_code]  == CSeqUtil::e_not_set  ||
  1657.          s_SeqDataToSeqUtil[from_code] == CSeqUtil::e_not_set ) {
  1658.         throw runtime_error("Requested conversion not implemented");
  1659.     }
  1660.     // Note: for now use old code to convert to ncbi2na with random
  1661.     // conversion of ambiguous characters.
  1662.     if ( (to_code == CSeq_data::e_Ncbi2na)  &&  (bAmbig == true) ) {
  1663.         return x_ConvertAmbig(in_seq, out_seq, to_code, uBeginIdx, uLength, seed);
  1664.     }
  1665.     const string* in_str = 0;
  1666.     const vector<char>* in_vec = 0;
  1667.     x_GetSeqFromSeqData(in_seq, &in_str, &in_vec);
  1668.     
  1669.     TSeqPos retval = 0;
  1670.     if ( in_str != 0 ) {
  1671.         string result;
  1672.         retval = CSeqConvert::Convert(*in_str, s_SeqDataToSeqUtil[from_code],
  1673.                                       uBeginIdx, uLength,
  1674.                                       result, s_SeqDataToSeqUtil[to_code]);
  1675.         CSeq_data temp(result, to_code);
  1676.         out_seq->Assign(temp);
  1677.     } else if ( in_vec != 0 ) {
  1678.         vector<char> result;
  1679.         retval = CSeqConvert::Convert(*in_vec, s_SeqDataToSeqUtil[from_code],
  1680.                                       uBeginIdx, uLength,
  1681.                                       result, s_SeqDataToSeqUtil[to_code]);
  1682.         CSeq_data temp(result, to_code);
  1683.         out_seq->Assign(temp);
  1684.     }
  1685.     return retval;
  1686. }
  1687. // Provide maximum packing without loss of information
  1688. TSeqPos CSeqportUtil_implementation::Pack
  1689. (CSeq_data*   in_seq,
  1690.  TSeqPos      uLength)
  1691.     const
  1692. {
  1693.     _ASSERT(in_seq != 0);
  1694.     CSeq_data::E_Choice from_code = in_seq->Which();
  1695.     _ASSERT(from_code != CSeq_data::e_not_set);
  1696.     
  1697.     if ( s_SeqDataToSeqUtil[from_code] == CSeqUtil::e_not_set ) {
  1698.         throw runtime_error("Unable tp pack requested coding");
  1699.     }
  1700.     
  1701.     // nothing to pack for proteins
  1702.     switch ( from_code ) {
  1703.     case CSeq_data::e_Iupacaa:
  1704.         return in_seq->GetIupacaa().Get().size();
  1705.     case CSeq_data::e_Ncbi8aa:
  1706.         return in_seq->GetNcbi8aa().Get().size();
  1707.     case CSeq_data::e_Ncbieaa:
  1708.         return in_seq->GetNcbieaa().Get().size();
  1709.     case CSeq_data::e_Ncbipaa:
  1710.         return in_seq->GetNcbipaa().Get().size();
  1711.     case CSeq_data::e_Ncbistdaa:
  1712.         return in_seq->GetNcbistdaa().Get().size();
  1713.     default:
  1714.         break;
  1715.     }
  1716.     // nothing to convert
  1717.     if ( from_code == CSeq_data::e_Ncbi2na  &&
  1718.          in_seq->GetNcbi2na().Get().size() * 4 <= uLength ) {
  1719.         return in_seq->GetNcbi2na().Get().size() * 4;
  1720.     }
  1721.     const string*       in_str = 0;
  1722.     const vector<char>* in_vec = 0;
  1723.     x_GetSeqFromSeqData(*in_seq, &in_str, &in_vec);
  1724.     vector<char> out_vec;
  1725.     CSeqUtil::TCoding coding = CSeqUtil::e_not_set;
  1726.     TSeqPos retval = 0;
  1727.     if ( in_str != 0 ) {
  1728.         retval =
  1729.             CSeqConvert::Pack(*in_str, s_SeqDataToSeqUtil[from_code],
  1730.                               out_vec, coding, uLength);
  1731.     } else if ( in_vec != 0 ) {
  1732.         retval = 
  1733.             CSeqConvert::Pack(*in_vec, s_SeqDataToSeqUtil[from_code],
  1734.                               out_vec, coding, uLength);
  1735.     }
  1736.     _ASSERT(coding == CSeqUtil::e_Ncbi2na  ||  coding == CSeqUtil::e_Ncbi4na);
  1737.     CSeq_data::E_Choice out_code = (coding == CSeqUtil::e_Ncbi2na) ?
  1738.         CSeq_data::e_Ncbi2na : CSeq_data::e_Ncbi4na;
  1739.     CSeq_data temp(out_vec, out_code);
  1740.     in_seq->Assign(temp);
  1741.     return retval;
  1742. }
  1743. // Method to quickly validate that a CSeq_data object contains valid data.
  1744. // FastValidate is a dispatch function that calls the appropriate
  1745. // private fast validation function.
  1746. bool CSeqportUtil_implementation::FastValidate
  1747. (const CSeq_data&   in_seq,
  1748.  TSeqPos            uBeginIdx,
  1749.  TSeqPos            uLength)
  1750.     const
  1751. {
  1752.     switch (in_seq.Which()) {
  1753.     case CSeq_data::e_Ncbi2na:
  1754.         return true; // ncbi2na sequences are always valid
  1755.     case CSeq_data::e_Ncbi4na:
  1756.         return true; // ncbi4na sequences are always valid
  1757.     case CSeq_data::e_Iupacna:
  1758.         return FastValidateIupacna(in_seq, uBeginIdx, uLength);
  1759.     case CSeq_data::e_Ncbieaa:
  1760.         return FastValidateNcbieaa(in_seq, uBeginIdx, uLength);
  1761.     case CSeq_data::e_Ncbistdaa:
  1762.         return FastValidateNcbistdaa(in_seq, uBeginIdx, uLength);
  1763.     case CSeq_data::e_Iupacaa:
  1764.         return FastValidateIupacaa(in_seq, uBeginIdx, uLength);
  1765.     default:
  1766.         throw runtime_error("Sequence could not be validated");
  1767.     }
  1768. }
  1769. // Function to perform full validation. Validate is a
  1770. // dispatch function that calls the appropriate private
  1771. // validation function.
  1772. void CSeqportUtil_implementation::Validate
  1773. (const CSeq_data&   in_seq,
  1774.  vector<TSeqPos>*   badIdx,
  1775.  TSeqPos            uBeginIdx,
  1776.  TSeqPos            uLength)
  1777.     const
  1778. {
  1779.     switch (in_seq.Which()) {
  1780.     case CSeq_data::e_Ncbi2na:
  1781.         return; // ncbi2na sequences are always valid
  1782.     case CSeq_data::e_Ncbi4na:
  1783.         return; // ncbi4na sequences are always valid
  1784.     case CSeq_data::e_Iupacna:
  1785.         ValidateIupacna(in_seq, badIdx, uBeginIdx, uLength);
  1786.         break;
  1787.     case CSeq_data::e_Ncbieaa:
  1788.         ValidateNcbieaa(in_seq, badIdx, uBeginIdx, uLength);
  1789.         break;
  1790.     case CSeq_data::e_Ncbistdaa:
  1791.         ValidateNcbistdaa(in_seq, badIdx, uBeginIdx, uLength);
  1792.         break;
  1793.     case CSeq_data::e_Iupacaa:
  1794.         ValidateIupacaa(in_seq, badIdx, uBeginIdx, uLength);
  1795.         break;
  1796.     default:
  1797.         throw runtime_error("Sequence could not be validated");
  1798.     }
  1799. }
  1800. // Function to find ambiguous bases and vector of indices of
  1801. // ambiguous bases in CSeq_data objects. GetAmbigs is a
  1802. // dispatch function that calls the appropriate private get
  1803. // ambigs function.
  1804. TSeqPos CSeqportUtil_implementation::GetAmbigs
  1805. (const CSeq_data&     in_seq,
  1806.  CSeq_data*           out_seq,
  1807.  vector<TSeqPos>*     out_indices,
  1808.  CSeq_data::E_Choice  to_code,
  1809.  TSeqPos              uBeginIdx,
  1810.  TSeqPos              uLength)
  1811.     const
  1812. {
  1813.     // Determine and call applicable GetAmbig method.
  1814.     switch (in_seq.Which()) {
  1815.     case CSeq_data::e_Ncbi4na:
  1816.         switch (to_code) {
  1817.         case CSeq_data::e_Ncbi2na:
  1818.             return GetAmbigs_ncbi4na_ncbi2na(in_seq, out_seq, out_indices,
  1819.                                              uBeginIdx, uLength);
  1820.         default:
  1821.             return 0;
  1822.         }
  1823.     case CSeq_data::e_Iupacna:
  1824.         switch (to_code) {
  1825.         case CSeq_data::e_Ncbi2na:
  1826.             return GetAmbigs_iupacna_ncbi2na(in_seq, out_seq, out_indices,
  1827.                                              uBeginIdx, uLength);
  1828.         default:
  1829.             return 0;
  1830.         }
  1831.     default:
  1832.         return 0;
  1833.     }
  1834. }
  1835. // Get a copy of in_seq from uBeginIdx through uBeginIdx + uLength-1
  1836. // and put in out_seq. See comments in alphabet.hpp for more information.
  1837. // GetCopy is a dispatch function.
  1838. TSeqPos CSeqportUtil_implementation::GetCopy
  1839. (const CSeq_data&   in_seq,
  1840.  CSeq_data*         out_seq,
  1841.  TSeqPos            uBeginIdx,
  1842.  TSeqPos            uLength)
  1843.     const
  1844. {
  1845.     // Do processing based on in_seq type
  1846.     switch (in_seq.Which()) {
  1847.     case CSeq_data::e_Ncbi2na:
  1848.         return GetNcbi2naCopy(in_seq, out_seq, uBeginIdx, uLength);
  1849.     case CSeq_data::e_Ncbi4na:
  1850.         return GetNcbi4naCopy(in_seq, out_seq, uBeginIdx, uLength);
  1851.     case CSeq_data::e_Iupacna:
  1852.         return GetIupacnaCopy(in_seq, out_seq, uBeginIdx, uLength);
  1853.     case CSeq_data::e_Ncbieaa:
  1854.         return GetNcbieaaCopy(in_seq, out_seq, uBeginIdx, uLength);
  1855.     case CSeq_data::e_Ncbistdaa:
  1856.         return GetNcbistdaaCopy(in_seq, out_seq, uBeginIdx, uLength);
  1857.     case CSeq_data::e_Iupacaa:
  1858.         return GetIupacaaCopy(in_seq, out_seq, uBeginIdx, uLength);
  1859.     default:
  1860.         throw runtime_error
  1861.             ("GetCopy() is not implemented for the requested sequence type");
  1862.     }
  1863. }
  1864. // Method to keep only a contiguous piece of a sequence beginning
  1865. // at uBeginIdx and uLength residues long. Keep is a
  1866. // dispatch function.
  1867. TSeqPos CSeqportUtil_implementation::Keep
  1868. (CSeq_data*   in_seq,
  1869.  TSeqPos      uBeginIdx,
  1870.  TSeqPos      uLength)
  1871.     const
  1872. {
  1873.     // Do proceessing based upon in_seq type
  1874.     switch (in_seq->Which()) {
  1875.     case CSeq_data::e_Ncbi2na:
  1876.         return KeepNcbi2na(in_seq, uBeginIdx, uLength);
  1877.     case CSeq_data::e_Ncbi4na:
  1878.         return KeepNcbi4na(in_seq, uBeginIdx, uLength);
  1879.     case CSeq_data::e_Iupacna:
  1880.         return KeepIupacna(in_seq, uBeginIdx, uLength);
  1881.     case CSeq_data::e_Ncbieaa:
  1882.         return KeepNcbieaa(in_seq, uBeginIdx, uLength);
  1883.     case CSeq_data::e_Ncbistdaa:
  1884.         return KeepNcbistdaa(in_seq, uBeginIdx, uLength);
  1885.     case CSeq_data::e_Iupacaa:
  1886.         return KeepIupacaa(in_seq, uBeginIdx, uLength);
  1887.     default:
  1888.         throw runtime_error("Cannot perform Keep on in_seq type.");
  1889.     }
  1890. }
  1891. // Append in_seq2 to in_seq1 and put result in out_seq. This
  1892. // is a dispatch function.
  1893. TSeqPos CSeqportUtil_implementation::Append
  1894. (CSeq_data*         out_seq,
  1895.  const CSeq_data&   in_seq1,
  1896.  TSeqPos            uBeginIdx1,
  1897.  TSeqPos            uLength1,
  1898.  const CSeq_data&   in_seq2,
  1899.  TSeqPos            uBeginIdx2,
  1900.  TSeqPos            uLength2)
  1901.     const
  1902. {
  1903.     // Check that in_seqs or of same type
  1904.     if(in_seq1.Which() != in_seq2.Which())
  1905.         throw runtime_error("Append in_seq types do not match.");
  1906.         
  1907.     // Check that out_seq is not null
  1908.     if(!out_seq) {
  1909.         return 0;
  1910.     }
  1911.     // Call applicable append method base on in_seq types
  1912.     switch (in_seq1.Which()) {
  1913.     case CSeq_data::e_Iupacna:
  1914.         return AppendIupacna(out_seq, in_seq1, uBeginIdx1, uLength1,
  1915.                              in_seq2, uBeginIdx2, uLength2);
  1916.     case CSeq_data::e_Ncbi2na:
  1917.         return AppendNcbi2na(out_seq, in_seq1, uBeginIdx1, uLength1,
  1918.                              in_seq2, uBeginIdx2, uLength2);
  1919.     case CSeq_data::e_Ncbi4na:
  1920.         return AppendNcbi4na(out_seq, in_seq1, uBeginIdx1, uLength1,
  1921.                              in_seq2, uBeginIdx2, uLength2);
  1922.     case CSeq_data::e_Ncbieaa:
  1923.         return AppendNcbieaa(out_seq, in_seq1, uBeginIdx1, uLength1,
  1924.                              in_seq2, uBeginIdx2, uLength2);
  1925.     case CSeq_data::e_Ncbistdaa:
  1926.         return AppendNcbistdaa(out_seq, in_seq1, uBeginIdx1, uLength1,
  1927.                                in_seq2, uBeginIdx2, uLength2);
  1928.     case CSeq_data::e_Iupacaa:
  1929.         return AppendIupacaa(out_seq, in_seq1, uBeginIdx1, uLength1,
  1930.                              in_seq2, uBeginIdx2, uLength2);
  1931.     default:
  1932.         throw runtime_error("Append for in_seq type not supported.");
  1933.     }
  1934. }
  1935. // Methods to complement na sequences. These are
  1936. // dispatch functions.
  1937. // Method to complement na sequence in place
  1938. TSeqPos CSeqportUtil_implementation::Complement
  1939. (CSeq_data*   in_seq,
  1940.  TSeqPos      uBeginIdx,
  1941.  TSeqPos      uLength)
  1942.     const
  1943. {
  1944.     _ASSERT(in_seq != 0);
  1945.     CSeq_data complement;
  1946.     TSeqPos retval = Complement(*in_seq, &complement, uBeginIdx, uLength);
  1947.     in_seq->Assign(complement);
  1948.     return retval;
  1949. }
  1950. // Method to complement na sequence in a copy out_seq
  1951. TSeqPos CSeqportUtil_implementation::Complement
  1952. (const CSeq_data&   in_seq,
  1953.  CSeq_data*         out_seq,
  1954.  TSeqPos            uBeginIdx,
  1955.  TSeqPos            uLength)
  1956.     const
  1957. {
  1958.     _ASSERT(out_seq != 0);
  1959.     if ( uLength == 0 ) {
  1960.         uLength = numeric_limits<TSeqPos>::max();
  1961.     }
  1962.     CSeq_data::E_Choice in_code = in_seq.Which();
  1963.     _ASSERT(in_code != CSeq_data::e_not_set);
  1964.     const string* in_str = 0;
  1965.     const vector<char>* in_vec = 0;
  1966.     x_GetSeqFromSeqData(in_seq, &in_str, &in_vec);
  1967.     TSeqPos retval = 0;
  1968.     if ( in_str ) {
  1969.         string out_str;
  1970.         retval = CSeqManip::Complement(*in_str, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength, out_str);
  1971.         CSeq_data temp(out_str, in_code);
  1972.         out_seq->Assign(temp);
  1973.     } else {
  1974.         vector<char> out_vec;
  1975.         retval = CSeqManip::Complement(*in_vec, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength, out_vec);
  1976.         CSeq_data temp(out_vec, in_code);
  1977.         out_seq->Assign(temp);
  1978.     }
  1979.     return retval;
  1980. }
  1981. // Methods to reverse na sequences. These are
  1982. // dispatch functions.
  1983. // Method to reverse na sequence in place
  1984. TSeqPos CSeqportUtil_implementation::Reverse
  1985. (CSeq_data*   in_seq,
  1986.  TSeqPos      uBeginIdx,
  1987.  TSeqPos      uLength)
  1988.     const
  1989. {
  1990.     CSeq_data temp;
  1991.     TSeqPos retval = Reverse(*in_seq, &temp, uBeginIdx, uLength);
  1992.     in_seq->Assign(temp);
  1993.     return retval;
  1994. }
  1995. // Method to reverse na sequence in a copy out_seq
  1996. TSeqPos CSeqportUtil_implementation::Reverse
  1997. (const CSeq_data&  in_seq,
  1998.  CSeq_data*        out_seq,
  1999.  TSeqPos           uBeginIdx,
  2000.  TSeqPos           uLength)
  2001.     const
  2002. {
  2003.     _ASSERT(out_seq != 0);
  2004.     if ( uLength == 0 ) {
  2005.         uLength = numeric_limits<TSeqPos>::max();
  2006.     }
  2007.     CSeq_data::E_Choice in_code = in_seq.Which();
  2008.     _ASSERT(in_code != CSeq_data::e_not_set);
  2009.     const string* in_str = 0;
  2010.     const vector<char>* in_vec = 0;
  2011.     x_GetSeqFromSeqData(in_seq, &in_str, &in_vec);
  2012.     TSeqPos retval = 0;
  2013.     if ( in_str ) {
  2014.         string out_str;
  2015.         retval = CSeqManip::Reverse(*in_str, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength, out_str);
  2016.         CSeq_data temp(out_str, in_code);
  2017.         out_seq->Assign(temp);
  2018.     } else {
  2019.         vector<char> out_vec;
  2020.         retval = CSeqManip::Reverse(*in_vec, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength, out_vec);
  2021.         CSeq_data temp(out_vec, in_code);
  2022.         out_seq->Assign(temp);
  2023.     }
  2024.     return retval;
  2025. }
  2026. // Methods to reverse-complement a sequence. These are
  2027. // dispatch functions.
  2028. // Method to reverse-complement na sequence in place
  2029. TSeqPos CSeqportUtil_implementation::ReverseComplement
  2030. (CSeq_data*  in_seq,
  2031.  TSeqPos     uBeginIdx,
  2032.  TSeqPos     uLength)
  2033.     const
  2034. {
  2035.     _ASSERT(in_seq != 0);
  2036.     CSeq_data::E_Choice in_code = in_seq->Which();
  2037.     _ASSERT(in_code != CSeq_data::e_not_set);
  2038.     string* in_str = 0;
  2039.     vector<char>* in_vec = 0;
  2040.     x_GetSeqFromSeqData(*in_seq, &in_str, &in_vec);
  2041.     if ( in_str ) {
  2042.         return CSeqManip::ReverseComplement(*in_str, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength);
  2043.     } else {
  2044.         return CSeqManip::ReverseComplement(*in_vec, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength);
  2045.     }
  2046. }
  2047. // Method to reverse-complement na sequence in a copy out_seq
  2048. TSeqPos CSeqportUtil_implementation::ReverseComplement
  2049. (const CSeq_data&  in_seq,
  2050.  CSeq_data*        out_seq,
  2051.  TSeqPos           uBeginIdx,
  2052.  TSeqPos           uLength)
  2053.     const
  2054. {
  2055.     _ASSERT(out_seq != 0);
  2056.     if ( uLength == 0 ) {
  2057.         uLength = numeric_limits<TSeqPos>::max();
  2058.     }
  2059.     CSeq_data::E_Choice in_code = in_seq.Which();
  2060.     _ASSERT(in_code != CSeq_data::e_not_set);
  2061.     const string* in_str = 0;
  2062.     const vector<char>* in_vec = 0;
  2063.     x_GetSeqFromSeqData(in_seq, &in_str, &in_vec);
  2064.     TSeqPos retval = 0;
  2065.     if ( in_str ) {
  2066.         string out_str;
  2067.         retval = CSeqManip::ReverseComplement(*in_str, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength, out_str);
  2068.         CSeq_data temp(out_str, in_code);
  2069.         out_seq->Assign(temp);
  2070.     } else {
  2071.         vector<char> out_vec;
  2072.         retval = CSeqManip::ReverseComplement(*in_vec, s_SeqDataToSeqUtil[in_code], uBeginIdx, uLength, out_vec);
  2073.         CSeq_data temp(out_vec, in_code);
  2074.         out_seq->Assign(temp);
  2075.     }
  2076.     return retval;
  2077. }
  2078. // Implement private worker functions called by public
  2079. // dispatch functions.
  2080. // Methods to convert between coding schemes
  2081. /*
  2082. // Convert in_seq from ncbi2na (1 byte) to iupacna (4 bytes)
  2083. // and put result in out_seq
  2084. TSeqPos CSeqportUtil_implementation::MapNcbi2naToIupacna
  2085. (const CSeq_data&   in_seq,
  2086.  CSeq_data*         out_seq,
  2087.  TSeqPos            uBeginIdx,
  2088.  TSeqPos            uLength)
  2089.     const
  2090. {
  2091.     // Save uBeginIdx and uLength for later use
  2092.     TSeqPos uBeginSav = uBeginIdx;
  2093.     TSeqPos uLenSav = uLength;
  2094.     // Get vector holding the in sequence
  2095.     const vector<char>& in_seq_data = in_seq.GetNcbi2na().Get();
  2096.     // Get string where the out sequence will go
  2097.     out_seq->Reset();
  2098.     string& out_seq_data = out_seq->SetIupacna().Set();
  2099.     // Validate uBeginSav
  2100.     if(uBeginSav >= 4*in_seq_data.size())
  2101.         return 0;
  2102.     // Adjust uLenSav
  2103.     if((uLenSav == 0 )|| ((uLenSav + uBeginSav )> 4*in_seq_data.size()))
  2104.         uLenSav = 4*in_seq_data.size() - uBeginSav;
  2105.     // Adjust uBeginIdx and uLength, if necessary
  2106.     Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 4, 1);
  2107.     // Declare iterator for in_seq
  2108.     vector<char>::const_iterator i_in;
  2109.     // Allocate string memory for result of conversion
  2110.     out_seq_data.resize(uLenSav);
  2111.     // Get pointer to data of out_seq_data (a string)
  2112.     string::iterator i_out = out_seq_data.begin()-1;
  2113.     // Determine begin and end bytes of in_seq_data
  2114.     vector<char>::const_iterator i_in_begin =
  2115.         in_seq_data.begin() + uBeginIdx/4;
  2116.     vector<char>::const_iterator i_in_end = i_in_begin + uLength/4;
  2117.     if((uLength % 4) != 0) ++i_in_end;
  2118.     --i_in_end;
  2119.     // Handle first input sequence byte
  2120.     unsigned int uVal =
  2121.         m_FastNcbi2naIupacna->m_Table[static_cast<unsigned char>(*i_in_begin)];
  2122.     char *pchar, *pval;
  2123.     pval = reinterpret_cast<char*>(&uVal);
  2124.     for(pchar = pval + uBeginSav - uBeginIdx; pchar < pval + 4; ++pchar)
  2125.         *(++i_out) = *pchar;
  2126.     if(i_in_begin == i_in_end)
  2127.         return uLenSav;
  2128.     ++i_in_begin;
  2129.     // Loop through in_seq_data and convert to out_seq
  2130.     for(i_in = i_in_begin; i_in != i_in_end; ++i_in) {
  2131.         uVal =
  2132.             m_FastNcbi2naIupacna->m_Table[static_cast<unsigned char>(*i_in)];
  2133.         pchar = reinterpret_cast<char*>(&uVal);
  2134.         (*(++i_out)) = (*(pchar++));
  2135.         (*(++i_out)) = (*(pchar++));
  2136.         (*(++i_out)) = (*(pchar++));
  2137.         (*(++i_out)) = (*(pchar++));
  2138.     }
  2139.     // Handle last byte of input data
  2140.     uVal =
  2141.         m_FastNcbi2naIupacna->m_Table[static_cast<unsigned char>(*i_in_end)];
  2142.     pval = reinterpret_cast<char*>(&uVal);
  2143.     TSeqPos uOverhang = (uBeginSav + uLenSav) % 4;
  2144.     uOverhang = (uOverhang ==0) ? 4 : uOverhang;
  2145.     for(pchar = pval; pchar < pval + uOverhang; ++pchar) {
  2146.         (*(++i_out)) = *pchar;
  2147.     }
  2148.     return uLenSav;
  2149. }
  2150. // Convert in_seq from ncbi2na (1 byte) to ncbi4na (2 bytes)
  2151. // and put result in out_seq
  2152. TSeqPos CSeqportUtil_implementation::MapNcbi2naToNcbi4na
  2153. (const CSeq_data&  in_seq,
  2154.  CSeq_data*        out_seq,
  2155.  TSeqPos           uBeginIdx,
  2156.  TSeqPos           uLength)
  2157.     const
  2158. {
  2159.     // Get vector holding the in sequence
  2160.     const vector<char>& in_seq_data = in_seq.GetNcbi2na().Get();
  2161.     // Get vector where out sequence will go
  2162.     out_seq->Reset();
  2163.     vector<char>& out_seq_data = out_seq->SetNcbi4na().Set();
  2164.     // Save uBeginIdx and uLength for later use as they
  2165.     // are modified below
  2166.     TSeqPos uBeginSav = uBeginIdx;
  2167.     TSeqPos uLenSav = uLength;
  2168.     // Check that uBeginSav is not beyond end of in_seq_data
  2169.     if(uBeginSav >= 4*in_seq_data.size())
  2170.         return 0;
  2171.     // Adjust uLenSav
  2172.     if((uLenSav == 0) || ((uBeginSav + uLenSav) > 4*in_seq_data.size()))
  2173.         uLenSav = 4*in_seq_data.size() - uBeginSav;
  2174.     // Adjust uBeginIdx and uLength, if necessary
  2175.     TSeqPos uOverhang =
  2176.         Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 4, 2);
  2177.     // Declare iterator for in_seq
  2178.     vector<char>::const_iterator i_in;
  2179.     // Allocate memory for out_seq_data
  2180.     TSeqPos uInBytes = (uLength + uOverhang)/4;
  2181.     if(((uLength + uOverhang) % 4) != 0) uInBytes++;
  2182.     vector<char>::size_type nOutBytes = 2*uInBytes;
  2183.     out_seq_data.resize(nOutBytes);
  2184.     // Get an iterator of out_seq_data
  2185.     vector<char>::iterator i_out = out_seq_data.begin()-1;
  2186.     // Determine begin and end bytes of in_seq_data
  2187.     vector<char>::const_iterator i_in_begin =
  2188.         in_seq_data.begin() + uBeginIdx/4;
  2189.     vector<char>::const_iterator i_in_end = i_in_begin + uInBytes;
  2190.     // Loop through in_seq_data and convert to out_seq_data
  2191.     for(i_in = i_in_begin; i_in != i_in_end; ++i_in) {
  2192.         unsigned short uVal =
  2193.             m_FastNcbi2naNcbi4na->m_Table[static_cast<unsigned char>(*i_in)];
  2194.         char* pch = reinterpret_cast<char*>(&uVal);
  2195.         (*(++i_out)) = (*(pch++));
  2196.         (*(++i_out)) = (*(pch++));
  2197.     }
  2198.     TSeqPos keepidx = uBeginSav - uBeginIdx;
  2199.     KeepNcbi4na(out_seq, keepidx, uLenSav);
  2200.     return uLenSav;
  2201. }
  2202. // Convert in_seq from ncbi4na (1 byte) to iupacna (2 bytes)
  2203. // and put result in out_seq
  2204. TSeqPos CSeqportUtil_implementation::MapNcbi4naToIupacna
  2205. (const CSeq_data& in_seq,
  2206.  CSeq_data*       out_seq,
  2207.  TSeqPos          uBeginIdx,
  2208.  TSeqPos          uLength)
  2209.     const
  2210. {
  2211.     // Save uBeginIdx and uLength for later use
  2212.     TSeqPos uBeginSav = uBeginIdx;
  2213.     TSeqPos uLenSav = uLength;
  2214.     // Get vector holding the in sequence
  2215.     const vector<char>& in_seq_data = in_seq.GetNcbi4na().Get();
  2216.     // Get string where the out sequence will go
  2217.     out_seq->Reset();
  2218.     string& out_seq_data = out_seq->SetIupacna().Set();
  2219.     // Validate uBeginSav
  2220.     if(uBeginSav >= 2*in_seq_data.size())
  2221.         return 0;
  2222.     // Adjust uLenSav
  2223.     if((uLenSav == 0 )|| ((uLenSav + uBeginSav )> 2*in_seq_data.size()))
  2224.         uLenSav = 2*in_seq_data.size() - uBeginSav;
  2225.     // Adjust uBeginIdx and uLength, if necessary
  2226.     Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 2, 1);
  2227.     // Declare iterator for in_seq
  2228.     vector<char>::const_iterator i_in;
  2229.     // Allocate string memory for result of conversion
  2230.     out_seq_data.resize(uLenSav);
  2231.     // Get pointer to data of out_seq_data (a string)
  2232.     string::iterator i_out = out_seq_data.begin() - 1;
  2233.     // Determine begin and end bytes of in_seq_data
  2234.     vector<char>::const_iterator i_in_begin =
  2235.         in_seq_data.begin() + uBeginIdx/2;
  2236.     vector<char>::const_iterator i_in_end = i_in_begin + uLength/2;
  2237.     if((uLength % 2) != 0) ++i_in_end;
  2238.     --i_in_end;
  2239.     // Handle first input sequence byte
  2240.     unsigned short uVal =
  2241.         m_FastNcbi4naIupacna->m_Table[static_cast<unsigned char>(*i_in_begin)];
  2242.     char *pchar, *pval;
  2243.     pval = reinterpret_cast<char*>(&uVal);
  2244.     for(pchar = pval + uBeginSav - uBeginIdx; pchar < pval + 2; ++pchar)
  2245.         *(++i_out) = *pchar;
  2246.     if(i_in_begin == i_in_end)
  2247.         return uLenSav;
  2248.     ++i_in_begin;
  2249.     // Loop through in_seq_data and convert to out_seq
  2250.     for(i_in = i_in_begin; i_in != i_in_end; ++i_in) {
  2251.         uVal =
  2252.             m_FastNcbi4naIupacna->m_Table[static_cast<unsigned char>(*i_in)];
  2253.         pchar = reinterpret_cast<char*>(&uVal);
  2254.         (*(++i_out)) = (*(pchar++));
  2255.         (*(++i_out)) = (*(pchar++));
  2256.     }
  2257.     // Handle last byte of input data
  2258.     uVal =
  2259.         m_FastNcbi4naIupacna->m_Table[static_cast<unsigned char>(*i_in_end)];
  2260.     pval = reinterpret_cast<char*>(&uVal);
  2261.     TSeqPos uOverhang = (uBeginSav + uLenSav) % 2;
  2262.     uOverhang = (uOverhang ==0) ? 2 : uOverhang;
  2263.     for(pchar = pval; pchar < pval + uOverhang; ++pchar)
  2264.         (*(++i_out)) = *pchar;
  2265.     return uLenSav;
  2266. }
  2267. */
  2268. // Function to convert iupacna (4 bytes) to ncbi2na (1 byte)
  2269. TSeqPos CSeqportUtil_implementation::MapIupacnaToNcbi2na
  2270. (const CSeq_data& in_seq,
  2271.  CSeq_data*       out_seq,
  2272.  TSeqPos          uBeginIdx,
  2273.  TSeqPos          uLength,
  2274.  bool             bAmbig,
  2275.  CRandom::TValue  seed)
  2276.     const
  2277. {
  2278.     // Get string holding the in_seq
  2279.     const string& in_seq_data = in_seq.GetIupacna().Get();
  2280.     // Get vector where the out sequence will go
  2281.     out_seq->Reset();
  2282.     vector<char>& out_seq_data = out_seq->SetNcbi2na().Set();
  2283.     // If uBeginIdx is after end of in_seq, return
  2284.     if(uBeginIdx >= in_seq_data.size())
  2285.         return 0;
  2286.     // Determine return value
  2287.     TSeqPos uLenSav = uLength;
  2288.     if((uLenSav == 0) || ((uLenSav + uBeginIdx)) > in_seq_data.size())
  2289.         uLenSav = in_seq_data.size() - uBeginIdx;
  2290.     // Adjust uBeginIdx and uLength, if necessary and get uOverhang
  2291.     TSeqPos uOverhang =
  2292.         Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 1, 4);
  2293.     // Allocate vector memory for result of conversion
  2294.     // Note memory for overhang is added below.
  2295.     vector<char>::size_type nBytes = uLength/4;
  2296.     out_seq_data.resize(nBytes);
  2297.     // Declare iterator for out_seq_data and determine begin and end
  2298.     vector<char>::iterator i_out;
  2299.     vector<char>::iterator i_out_begin = out_seq_data.begin();
  2300.     vector<char>::iterator i_out_end = i_out_begin + uLength/4;
  2301.     // Determine begin of in_seq_data
  2302.     string::const_iterator i_in = in_seq_data.begin() + uBeginIdx;
  2303.     if(bAmbig)
  2304.         {
  2305.             // Do random disambiguation
  2306.             unsigned char c1, c2;
  2307.             CRandom::TValue rv;
  2308.             // Declare a random number generator and set seed
  2309.             CRandom rg;
  2310.             rg.SetSeed(seed);
  2311.     // Do disambiguation by converting Iupacna to Ncbi4na
  2312.     // deterministically and then converting from Ncbi4na to Ncbi2na
  2313.     // with random disambiguation
  2314.     // Loop through the out_seq_data converting 4 Iupacna bytes to
  2315.     // one Ncbi2na byte. in_seq_data.size() % 4 bytes at end of
  2316.     // input handled separately below.
  2317.             for(i_out = i_out_begin; i_out != i_out_end; ++i_out)
  2318.                 {
  2319.                     // Determine first Ncbi4na byte from 1st two Iupacna bytes
  2320.                     c1 =
  2321.                         m_FastIupacnaNcbi4na->m_Table
  2322.                         [0][static_cast<unsigned char>(*i_in)] |
  2323.                         m_FastIupacnaNcbi4na->m_Table
  2324.                         [1][static_cast<unsigned char>(*(i_in+1))];
  2325.     // Determine second Ncbi4na byte from 2nd two Iupacna bytes
  2326.                     c2 =
  2327.                         m_FastIupacnaNcbi4na->m_Table
  2328.                         [0][static_cast<unsigned char>(*(i_in+2))]|
  2329.                         m_FastIupacnaNcbi4na->m_Table
  2330.                         [1][static_cast<unsigned char>(*(i_in+3))];
  2331.     // Randomly pick disambiguated Ncbi4na bytes
  2332.                     rv = rg.GetRand() % 16;
  2333.                     c1 &= m_Masks->m_Table[c1].cMask[rv];
  2334.                     rv = rg.GetRand() % 16;
  2335.                     c2 &= m_Masks->m_Table[c2].cMask[rv];
  2336.     // Convert from Ncbi4na to Ncbi2na
  2337.                     (*i_out) = m_FastNcbi4naNcbi2na->m_Table[0][c1] |
  2338.                         m_FastNcbi4naNcbi2na->m_Table[1][c2];
  2339.     // Increment input sequence iterator.
  2340.                     i_in+=4;
  2341.                 }
  2342.             // Handle overhang at end of in_seq
  2343.             switch (uOverhang) {
  2344.             case 1:
  2345.                 c1 =
  2346.                     m_FastIupacnaNcbi4na->m_Table
  2347.                     [0][static_cast<unsigned char>(*i_in)];
  2348.                 rv = rg.GetRand() % 16;
  2349.                 c1 &= m_Masks->m_Table[c1].cMask[rv];
  2350.                 out_seq_data.push_back(m_FastNcbi4naNcbi2na->m_Table[0][c1]);
  2351.                 break;
  2352.             case 2:
  2353.                 c1 =
  2354.                     m_FastIupacnaNcbi4na->m_Table
  2355.                     [0][static_cast<unsigned char>(*i_in)] |
  2356.                     m_FastIupacnaNcbi4na->m_Table
  2357.                     [1][static_cast<unsigned char>(*(i_in+1))];
  2358.                 rv = rg.GetRand() % 16;
  2359.                 c1 &= m_Masks->m_Table[c1].cMask[rv];
  2360.                 out_seq_data.push_back(m_FastNcbi4naNcbi2na->m_Table[0][c1]);
  2361.                 break;
  2362.             case 3:
  2363.                 c1 =
  2364.                     m_FastIupacnaNcbi4na->m_Table
  2365.                     [0][static_cast<unsigned char>(*i_in)] |
  2366.                     m_FastIupacnaNcbi4na->m_Table
  2367.                     [1][static_cast<unsigned char>(*(i_in+1))];
  2368.                 c2 =
  2369.                     m_FastIupacnaNcbi4na->m_Table
  2370.                     [0][static_cast<unsigned char>(*(i_in+2))];
  2371.                 rv = rg.GetRand() % 16;
  2372.                 c2 &= m_Masks->m_Table[c1].cMask[rv];
  2373.                 rv = rg.GetRand() % 16;
  2374.                 c2 &= m_Masks->m_Table[c2].cMask[rv];
  2375.                 out_seq_data.push_back(m_FastNcbi4naNcbi2na->m_Table[0][c1] |
  2376.                                        m_FastNcbi4naNcbi2na->m_Table[1][c2]);
  2377.             }
  2378.         }
  2379.     else
  2380.         {
  2381.             // Pack uLength input characters into out_seq_data
  2382.             for(i_out = i_out_begin; i_out != i_out_end; ++i_out)
  2383.                 {
  2384.                     (*i_out) =
  2385.                         m_FastIupacnaNcbi2na->m_Table
  2386.                         [0][static_cast<unsigned char>(*(i_in))] |
  2387.                         m_FastIupacnaNcbi2na->m_Table
  2388.                         [1][static_cast<unsigned char>(*(i_in+1))] |
  2389.                         m_FastIupacnaNcbi2na->m_Table
  2390.                         [2][static_cast<unsigned char>(*(i_in+2))] |
  2391.                         m_FastIupacnaNcbi2na->m_Table
  2392.                         [3][static_cast<unsigned char>(*(i_in+3))];
  2393.                     i_in+=4;
  2394.                 }
  2395.             // Handle overhang
  2396.             char ch = 'x00';
  2397.             for(TSeqPos i = 0; i < uOverhang; i++)
  2398.                 ch |=
  2399.                     m_FastIupacnaNcbi2na->m_Table
  2400.                     [i][static_cast<unsigned char>(*(i_in+i))];
  2401.             if(uOverhang > 0)
  2402.                 out_seq_data.push_back(ch);
  2403.         }
  2404.     return uLenSav;
  2405. }
  2406. /*
  2407. // Function to convert iupacna (2 bytes) to ncbi4na (1 byte)
  2408. TSeqPos CSeqportUtil_implementation::MapIupacnaToNcbi4na
  2409. (const CSeq_data&  in_seq,
  2410.  CSeq_data*        out_seq,
  2411.  TSeqPos           uBeginIdx,
  2412.  TSeqPos           uLength)
  2413.     const
  2414. {
  2415.     // Get string holding the in_seq
  2416.     const string& in_seq_data = in_seq.GetIupacna().Get();
  2417.     // Get vector where the out sequence will go
  2418.     out_seq->Reset();
  2419.     vector<char>& out_seq_data = out_seq->SetNcbi4na().Set();
  2420.     // If uBeginIdx beyond end of in_seq, return
  2421.     if(uBeginIdx >= in_seq_data.size())
  2422.         return 0;
  2423.     // Determine return value
  2424.     TSeqPos uLenSav = uLength;
  2425.     if((uLenSav == 0) || (uLenSav + uBeginIdx) > in_seq_data.size())
  2426.         uLenSav = in_seq_data.size() - uBeginIdx;
  2427.     // Adjust uBeginIdx and uLength and get uOverhang
  2428.     TSeqPos uOverhang =
  2429.         Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 1, 2);
  2430.     // Allocate vector memory for result of conversion
  2431.     // Note memory for overhang is added below.
  2432.     vector<char>::size_type nBytes = uLength/2;
  2433.     out_seq_data.resize(nBytes);
  2434.     // Declare iterator for out_seq_data and determine begin and end
  2435.     vector<char>::iterator i_out;
  2436.     vector<char>::iterator i_out_begin = out_seq_data.begin();
  2437.     vector<char>::iterator i_out_end = i_out_begin + uLength/2;
  2438.     // Determine begin of in_seq_data offset by 1
  2439.     string::const_iterator i_in = in_seq_data.begin() + uBeginIdx;
  2440.     // Pack uLength input characters into out_seq_data
  2441.     for(i_out = i_out_begin; i_out != i_out_end; ++i_out) {
  2442.         (*i_out) =
  2443.             m_FastIupacnaNcbi4na->m_Table
  2444.             [0][static_cast<unsigned char>(*(i_in))] |
  2445.             m_FastIupacnaNcbi4na->m_Table
  2446.             [1][static_cast<unsigned char>(*(i_in+1))];
  2447.         i_in+=2;
  2448.     }
  2449.     // Handle overhang
  2450.     char ch = 'x00';
  2451.     if (uOverhang > 0) {
  2452.         ch |=
  2453.             m_FastIupacnaNcbi4na->
  2454.             m_Table[0][static_cast<unsigned char>(*i_in)];
  2455.         out_seq_data.push_back(ch);
  2456.     }
  2457.     return uLenSav;
  2458. }
  2459. */
  2460. // Function to convert ncbi4na (2 bytes) to ncbi2na (1 byte)
  2461. TSeqPos CSeqportUtil_implementation::MapNcbi4naToNcbi2na
  2462. (const CSeq_data&  in_seq,
  2463.  CSeq_data*        out_seq,
  2464.  TSeqPos           uBeginIdx,
  2465.  TSeqPos           uLength,
  2466.  bool              bAmbig,
  2467.  CRandom::TValue   seed)
  2468.     const
  2469. {
  2470.     // Get vector holding the in_seq
  2471.     const vector<char>& in_seq_data = in_seq.GetNcbi4na().Get();
  2472.     // Get vector where the out sequence will go
  2473.     out_seq->Reset();
  2474.     vector<char>& out_seq_data = out_seq->SetNcbi2na().Set();
  2475.     // Save uBeginIdx and uLength as they will be modified below
  2476.     TSeqPos uBeginSav = uBeginIdx;
  2477.     TSeqPos uLenSav = uLength;
  2478.     // Check that uBeginSav is not beyond end of in_seq
  2479.     if(uBeginSav >= 2*in_seq_data.size())
  2480.         return 0;
  2481.     // Adjust uLenSav if needed
  2482.     if((uLenSav == 0) || ((uBeginSav + uLenSav) > 2*in_seq_data.size()))
  2483.         uLenSav = 2*in_seq_data.size() - uBeginSav;
  2484.     // Adjust uBeginIdx and uLength and get uOverhang
  2485.     TSeqPos uOverhang =
  2486.         Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 2, 4);
  2487.     // Allocate vector memory for result of conversion
  2488.     // Note memory for overhang is added below.
  2489.     vector<char>::size_type nBytes = uLength/4;
  2490.     out_seq_data.resize(nBytes);
  2491.     // Declare iterator for out_seq_data and determine begin and end
  2492.     vector<char>::iterator i_out;
  2493.     vector<char>::iterator i_out_begin = out_seq_data.begin();
  2494.     vector<char>::iterator i_out_end = i_out_begin + uLength/4;
  2495.     // Determine begin of in_seq_data
  2496.     vector<char>::const_iterator i_in = in_seq_data.begin() + uBeginIdx/2;
  2497.     // Do random disambiguation
  2498.     if(bAmbig)
  2499.         {
  2500.             // Declare a random number generator and set seed
  2501.             CRandom rg;
  2502.             rg.SetSeed(seed);
  2503.             // Pack uLength input bytes into out_seq_data
  2504.             for(i_out = i_out_begin; i_out != i_out_end; ++i_out)
  2505.                 {
  2506.                     // Disambiguate
  2507.                     unsigned char c1 = static_cast<unsigned char>(*i_in);
  2508.                     unsigned char c2 = static_cast<unsigned char>(*(i_in+1));
  2509.                     CRandom::TValue rv = rg.GetRand() % 16;
  2510.                     c1 &= m_Masks->m_Table[c1].cMask[rv];
  2511.                     rv = rg.GetRand() % 16;
  2512.                     c2 &= m_Masks->m_Table[c2].cMask[rv];
  2513.                     // Convert
  2514.                     (*i_out) =
  2515.                         m_FastNcbi4naNcbi2na->m_Table[0][c1] |
  2516.                         m_FastNcbi4naNcbi2na->m_Table[1][c2];
  2517.                     i_in+=2;
  2518.                 }
  2519.             // Handle overhang
  2520.             char ch = 'x00';
  2521.             if(uOverhang > 0)
  2522.                 {
  2523.                     // Disambiguate
  2524.                     unsigned char c1 = static_cast<unsigned char>(*i_in);
  2525.                     CRandom::TValue rv = rg.GetRand() % 16;
  2526.                     c1 &= m_Masks->m_Table[c1].cMask[rv];
  2527.             // Convert
  2528.                     ch |= m_FastNcbi4naNcbi2na->m_Table[0][c1];
  2529.                 }
  2530.             if(uOverhang == 3)
  2531.                 {
  2532.                     // Disambiguate
  2533.                     unsigned char c1 = static_cast<unsigned char>(*(++i_in));
  2534.                     CRandom::TValue rv = rg.GetRand() % 16;
  2535.                     c1 &= m_Masks->m_Table[c1].cMask[rv];
  2536.             // Convert
  2537.                     ch |= m_FastNcbi4naNcbi2na->m_Table[1][c1];
  2538.                 }
  2539.             if(uOverhang > 0)
  2540.                 {
  2541.                     out_seq_data.push_back(ch);
  2542.                 }
  2543.         }
  2544.     // Do not do random disambiguation
  2545.     else
  2546.         {
  2547.             // Pack uLength input bytes into out_seq_data
  2548.             for(i_out = i_out_begin; i_out != i_out_end; ++i_out) {
  2549.                 (*i_out) =
  2550.                     m_FastNcbi4naNcbi2na->m_Table
  2551.                     [0][static_cast<unsigned char>(*i_in)] |
  2552.                     m_FastNcbi4naNcbi2na->m_Table
  2553.                     [1][static_cast<unsigned char>(*(i_in+1))];
  2554.                 i_in+=2;
  2555.             }
  2556.             // Handle overhang
  2557.             char ch = 'x00';
  2558.             if(uOverhang > 0)
  2559.                 ch |= m_FastNcbi4naNcbi2na->m_Table
  2560.                     [0][static_cast<unsigned char>(*i_in)];
  2561.             if(uOverhang == 3)
  2562.                 ch |= m_FastNcbi4naNcbi2na->m_Table
  2563.                     [1][static_cast<unsigned char>(*(++i_in))];
  2564.             if(uOverhang > 0)
  2565.                 out_seq_data.push_back(ch);
  2566.         }
  2567.     TSeqPos keepidx = uBeginSav - uBeginIdx;
  2568.     KeepNcbi2na(out_seq, keepidx, uLenSav);
  2569.     return uLenSav;
  2570. }
  2571. /*
  2572. // Function to convert iupacaa (byte) to ncbieaa (byte)
  2573. TSeqPos CSeqportUtil_implementation::MapIupacaaToNcbieaa
  2574. (const CSeq_data&  in_seq,
  2575.  CSeq_data*        out_seq,
  2576.  TSeqPos           uBeginIdx,
  2577.  TSeqPos           uLength)
  2578.     const
  2579. {
  2580.     // Get read-only reference to in_seq data
  2581.     const string& in_seq_data = in_seq.GetIupacaa().Get();
  2582.     // Get read & write reference to out_seq data
  2583.     out_seq->Reset();
  2584.     string& out_seq_data = out_seq->SetNcbieaa().Set();
  2585.     // If uBeginIdx beyond end of in_seq, return
  2586.     if(uBeginIdx >= in_seq_data.size())
  2587.         return 0;
  2588.     // Adjust uBeginIdx and uLength, if necessary
  2589.     Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 1, 1);
  2590.     // Allocate memory for out_seq
  2591.     out_seq_data.resize(uLength);
  2592.     // Declare iterator for out_seq_data
  2593.     string::iterator i_out = out_seq_data.begin();
  2594.     // Declare iterator for in_seq_data and determine begin and end
  2595.     string::const_iterator i_in;
  2596.     string::const_iterator i_in_begin = in_seq_data.begin() + uBeginIdx;
  2597.     string::const_iterator i_in_end = i_in_begin + uLength;
  2598.     // Loop through input and convert to output
  2599.     for(i_in = i_in_begin; i_in != i_in_end; ++i_in)
  2600.         (*(i_out++)) =
  2601.             m_IupacaaNcbieaa->m_Table[static_cast<unsigned char>(*i_in)];
  2602.     return uLength;
  2603. }
  2604. // Function to convert ncbieaa (byte) to iupacaa (byte)
  2605. TSeqPos CSeqportUtil_implementation::MapNcbieaaToIupacaa
  2606. (const CSeq_data&   in_seq,
  2607.  CSeq_data*         out_seq,
  2608.  TSeqPos            uBeginIdx,
  2609.  TSeqPos            uLength)
  2610.     const
  2611. {
  2612.     // Get read-only reference to in_seq data
  2613.     const string& in_seq_data = in_seq.GetNcbieaa().Get();
  2614.     // Get read & write reference to out_seq data
  2615.     out_seq->Reset();
  2616.     string& out_seq_data = out_seq->SetIupacaa().Set();
  2617.     // If uBeginIdx beyond end of in_seq, return
  2618.     if(uBeginIdx >= in_seq_data.size())
  2619.         return 0;
  2620.     // Adjust uBeginIdx and uLength, if necessary
  2621.     Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 1, 1);
  2622.     // Allocate memory for out_seq
  2623.     out_seq_data.resize(uLength);
  2624.     // Declare iterator for out_seq_data
  2625.     string::iterator i_out = out_seq_data.begin();
  2626.     // Declare iterator for in_seq_data and determine begin and end
  2627.     string::const_iterator i_in;
  2628.     string::const_iterator i_in_begin = in_seq_data.begin() + uBeginIdx;
  2629.     string::const_iterator i_in_end = i_in_begin + uLength;
  2630.     // Loop through input and convert to output
  2631.     for(i_in = i_in_begin; i_in != i_in_end; ++i_in)
  2632.         (*(i_out++)) =
  2633.             m_NcbieaaIupacaa->m_Table[static_cast<unsigned char>(*i_in)];
  2634.     return uLength;
  2635. }
  2636. // Function to convert iupacaa (byte) to ncbistdaa (byte)
  2637. TSeqPos CSeqportUtil_implementation::MapIupacaaToNcbistdaa
  2638. (const CSeq_data&  in_seq,
  2639.  CSeq_data*        out_seq,
  2640.  TSeqPos           uBeginIdx,
  2641.  TSeqPos           uLength)
  2642.     const
  2643. {
  2644.     // Get read-only reference to in_seq data
  2645.     const string& in_seq_data = in_seq.GetIupacaa().Get();
  2646.     // Get read & write reference to out_seq data
  2647.     out_seq->Reset();
  2648.     vector<char>& out_seq_data = out_seq->SetNcbistdaa().Set();
  2649.     // If uBeginIdx beyond end of in_seq, return
  2650.     if(uBeginIdx >= in_seq_data.size())
  2651.         return 0;
  2652.     // Adjust uBeginIdx and uLength, if necessary
  2653.     Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 1, 1);
  2654.     // Allocate memory for out_seq
  2655.     out_seq_data.resize(uLength);
  2656.     // Declare iterator for out_seq_data
  2657.     vector<char>::iterator i_out = out_seq_data.begin();
  2658.     // Declare iterator for in_seq_data and determine begin and end
  2659.     string::const_iterator i_in;
  2660.     string::const_iterator i_in_begin = in_seq_data.begin() + uBeginIdx;
  2661.     string::const_iterator i_in_end = i_in_begin + uLength;
  2662.     // Loop through input and convert to output
  2663.     for(i_in = i_in_begin; i_in != i_in_end; ++i_in)
  2664.         (*(i_out++)) =
  2665.             m_IupacaaNcbistdaa->m_Table[static_cast<unsigned char>(*i_in)];
  2666.     return uLength;
  2667. }
  2668. // Function to convert ncbieaa (byte) to ncbistdaa (byte)
  2669. TSeqPos CSeqportUtil_implementation::MapNcbieaaToNcbistdaa
  2670. (const CSeq_data&   in_seq,
  2671.  CSeq_data*         out_seq,
  2672.  TSeqPos            uBeginIdx,
  2673.  TSeqPos            uLength)
  2674.     const
  2675. {
  2676.     // Get read-only reference to in_seq data
  2677.     const string& in_seq_data = in_seq.GetNcbieaa().Get();
  2678.     // Get read & write reference to out_seq data
  2679.     out_seq->Reset();
  2680.     vector<char>& out_seq_data = out_seq->SetNcbistdaa().Set();
  2681.     // If uBeginIdx beyond end of in_seq, return
  2682.     if(uBeginIdx >= in_seq_data.size())
  2683.         return 0;
  2684.     // Adjust uBeginIdx and uLength, if necessary
  2685.     Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 1, 1);
  2686.     // Allocate memory for out_seq
  2687.     out_seq_data.resize(uLength);
  2688.     // Declare iterator for out_seq_data
  2689.     vector<char>::iterator i_out = out_seq_data.begin();
  2690.     // Declare iterator for in_seq_data and determine begin and end
  2691.     string::const_iterator i_in;
  2692.     string::const_iterator i_in_begin = in_seq_data.begin() + uBeginIdx;
  2693.     string::const_iterator i_in_end = i_in_begin + uLength;
  2694.     // Loop through input and convert to output
  2695.     for(i_in = i_in_begin; i_in != i_in_end; ++i_in)
  2696.         (*(i_out++)) =
  2697.             m_NcbieaaNcbistdaa->m_Table[static_cast<unsigned char>(*i_in)];
  2698.     return uLength;
  2699. }
  2700. // Function to convert ncbistdaa (byte) to ncbieaa (byte)
  2701. TSeqPos CSeqportUtil_implementation::MapNcbistdaaToNcbieaa
  2702. (const CSeq_data&  in_seq,
  2703.  CSeq_data*        out_seq,
  2704.  TSeqPos           uBeginIdx,
  2705.  TSeqPos           uLength)
  2706.     const
  2707. {
  2708.     // Get read-only reference to in_seq data
  2709.     const vector<char>& in_seq_data = in_seq.GetNcbistdaa().Get();
  2710.     // Get read & write reference to out_seq data
  2711.     out_seq->Reset();
  2712.     string& out_seq_data = out_seq->SetNcbieaa().Set();
  2713.     // If uBeginIdx beyond end of in_seq, return
  2714.     if(uBeginIdx >= in_seq_data.size())
  2715.         return 0;
  2716.     // Adjust uBeginIdx and uLength if necessary
  2717.     Adjust(&uBeginIdx, &uLength, in_seq_data.size(), 1, 1);