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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seqdbvol.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:46:54  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seqdbvol.cpp,v 1000.1 2004/06/01 19:46:54 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:  Kevin Bealer
  35.  *
  36.  */
  37. #include <ncbi_pch.hpp>
  38. #include "seqdbvol.hpp"
  39. BEGIN_NCBI_SCOPE
  40. char CSeqDBVol::GetSeqType(void) const
  41. {
  42.     return x_GetSeqType();
  43. }
  44. char CSeqDBVol::x_GetSeqType(void) const
  45. {
  46.     return m_Idx.GetSeqType();
  47. }
  48. Int4 CSeqDBVol::GetSeqLength(Uint4 oid, bool approx) const
  49. {
  50.     Uint4 start_offset = 0;
  51.     Uint4 end_offset   = 0;
  52.     
  53.     Int4 length = -1;
  54.     
  55.     if (! m_Idx.GetSeqStartEnd(oid, start_offset, end_offset))
  56.         return -1;
  57.     
  58.     char seqtype = m_Idx.GetSeqType();
  59.     
  60.     if (kSeqTypeProt == seqtype) {
  61.         // Subtract one, for the inter-sequence null.
  62.         length = end_offset - start_offset - 1;
  63.     } else if (kSeqTypeNucl == seqtype) {
  64.         Int4 whole_bytes = end_offset - start_offset - 1;
  65.         
  66.         if (approx) {
  67.             // Same principle as below - but use lower bits of oid
  68.             // instead of fetching the actual last byte.  this should
  69.             // correct for bias, unless sequence length modulo 4 has a
  70.             // significant statistical bias, which seems unlikely to
  71.             // me.
  72.             
  73.             length = (whole_bytes * 4) + (oid & 0x03);
  74.         } else {
  75.             // The last byte is partially full; the last two bits of
  76.             // the last byte store the number of nucleotides in the
  77.             // last byte (0 to 3).
  78.             
  79.             char amb_char = 0;
  80.             
  81.             m_Seq.ReadBytes(& amb_char, end_offset - 1, end_offset);
  82.             
  83.             Int4 remainder = amb_char & 3;
  84.             length = (whole_bytes * 4) + remainder;
  85.         }
  86.     }
  87.         
  88.     return length;
  89. }
  90. static CFastMutex s_MapNaMutex;
  91. static vector<Uint1>
  92. s_SeqDBMapNA2ToNA4Setup(void)
  93. {
  94.     vector<Uint1> translated;
  95.     translated.resize(512);
  96.     
  97.     Uint1 convert[16] = {17,  18,  20,  24,  33,  34,  36,  40,
  98.                          65,  66,  68,  72, 129, 130, 132, 136};
  99.     Int2 pair1 = 0;
  100.     Int2 pair2 = 0;
  101.     
  102.     for(pair1 = 0; pair1 < 16; pair1++) {
  103.         for(pair2 = 0; pair2 < 16; pair2++) {
  104.             Int2 index = (pair1 * 16 + pair2) * 2;
  105.             
  106.             translated[index]   = convert[pair1];
  107.             translated[index+1] = convert[pair2];
  108.         }
  109.     }
  110.     
  111.     return translated;
  112. }
  113. static void
  114. s_SeqDBMapNA2ToNA4(const char   * buf2bit,
  115.                    vector<char> & buf4bit,
  116.                    int            base_length)
  117. {
  118.     static vector<Uint1> expanded = s_SeqDBMapNA2ToNA4Setup();
  119.     
  120.     Uint4 estimated_length = (base_length + 1)/2;
  121.     buf4bit.reserve(estimated_length);
  122.     
  123.     int inp_chars = base_length/4;
  124.     
  125.     for(int i=0; i<inp_chars; i++) {
  126.         Uint4 inp_char = (buf2bit[i] & 0xFF);
  127.         
  128.         buf4bit.push_back(expanded[ (inp_char*2)     ]);
  129.         buf4bit.push_back(expanded[ (inp_char*2) + 1 ]);
  130.     }
  131.     
  132.     int bases_remain = base_length - (inp_chars*4);
  133.     
  134.     if (bases_remain) {
  135.         Uint1 remainder_bits = 2 * bases_remain;
  136.         Uint1 remainder_mask = (0xFF << (8 - remainder_bits)) & 0xFF;
  137.         Uint4 last_masked = buf2bit[inp_chars] & remainder_mask;
  138.         
  139.         buf4bit.push_back(expanded[ (last_masked*2) ]);
  140.         
  141.         if (bases_remain > 2) {
  142.             buf4bit.push_back(expanded[ (last_masked*2)+1 ]);
  143.         }
  144.     }
  145.     
  146.     _ASSERT(estimated_length == buf4bit.size());
  147. }
  148. static vector<Uint1>
  149. s_SeqDBMapNA2ToNA8Setup(void)
  150. {
  151.     // Builds a table; each two bit slice holds 0,1,2 or 3.  These are
  152.     // converted to whole bytes containing 1,2,4, or 8, respectively.
  153.     
  154.     vector<Uint1> translated;
  155.     translated.reserve(1024);
  156.     
  157.     for(Uint4 i = 0; i<256; i++) {
  158.         Uint4 p1 = (i >> 6) & 0x3;
  159.         Uint4 p2 = (i >> 4) & 0x3;
  160.         Uint4 p3 = (i >> 2) & 0x3;
  161.         Uint4 p4 = i & 0x3;
  162.         
  163.         translated.push_back(1 << p1);
  164.         translated.push_back(1 << p2);
  165.         translated.push_back(1 << p3);
  166.         translated.push_back(1 << p4);
  167.     }
  168.     
  169.     return translated;
  170. }
  171. static void
  172. s_SeqDBMapNA2ToNA8(const char   * buf2bit,
  173.                    vector<char> & buf8bit,
  174.                    Uint4          base_length,
  175.                    bool           sentinel_bytes)
  176. {
  177.     static vector<Uint1> expanded = s_SeqDBMapNA2ToNA8Setup();
  178.     
  179.     int sreserve = 0;
  180.     
  181.     if (sentinel_bytes) {
  182.         sreserve = 2;
  183.         buf8bit.push_back((unsigned char)(0));
  184.     }
  185.     
  186.     buf8bit.reserve(base_length + sreserve);
  187.     
  188.     int whole_input_chars = base_length/4;
  189.     
  190.     // In a nucleotide search, this loop is probably a noticeable time
  191.     // consumer, at least relative to the CSeqDB universe.  Each input
  192.     // byte is used to look up a 4 byte output translation.  That four
  193.     // byte section is copied to the output vector.  By pre-processing
  194.     // the arithmetic in the ~Setup() function, we can just pull bytes
  195.     // from a vector.
  196.     
  197.     for(int i = 0; i < whole_input_chars; i++) {
  198.         Uint4 table_offset = (buf2bit[i] & 0xFF) * 4;
  199.         
  200.         buf8bit.push_back(expanded[ table_offset ]);
  201.         buf8bit.push_back(expanded[ table_offset + 1 ]);
  202.         buf8bit.push_back(expanded[ table_offset + 2 ]);
  203.         buf8bit.push_back(expanded[ table_offset + 3 ]);
  204.     }
  205.     
  206.     int bases_remain = base_length & 0x3;
  207.     
  208.     if (bases_remain) {
  209.         // We use the last byte of the input to look up a four byte
  210.         // translation; but we only use the bytes of it that we need.
  211.         
  212.         Uint4 table_offset = (buf2bit[whole_input_chars] & 0xFF) * 4;
  213.         
  214.         while(bases_remain--) {
  215.             buf8bit.push_back(expanded[ ++table_offset ]);
  216.         }
  217.     }
  218.     
  219.     if (sentinel_bytes) {
  220.         buf8bit.push_back((unsigned char)(0));
  221.     }
  222.     
  223.     _ASSERT(base_length == (buf8bit.size() - sreserve));
  224. }
  225. #if 0
  226. static vector<Uint1>
  227. s_SeqDBMapNcbiNA4ToBlastNA4Setup(void)
  228. {
  229.     vector<Uint1> translated;
  230.     translated.resize(256);
  231.     
  232.     // This mapping stolen., er, courtesy of blastkar.c.
  233.     
  234.     Uint1 trans_ncbi4na_to_blastna[] = {
  235.         15, /* Gap, 0 */
  236.         0,  /* A,   1 */
  237.         1,  /* C,   2 */
  238.         6,  /* M,   3 */
  239.         2,  /* G,   4 */
  240.         4,  /* R,   5 */
  241.         9,  /* S,   6 */
  242.         13, /* V,   7 */
  243.         3,  /* T,   8 */
  244.         8,  /* W,   9 */
  245.         5,  /* Y,  10 */
  246.         12, /* H,  11 */
  247.         7,  /* K,  12 */
  248.         11, /* D,  13 */
  249.         10, /* B,  14 */
  250.         14  /* N,  15 */
  251.     };
  252.     
  253.     for(int i = 0; i<256; i++) {
  254.         int a1 = (i >> 4) & 0xF;
  255.         int a2 = i & 0xF;
  256.         
  257.         int b1 = trans_ncbi4na_to_blastna[a1];
  258.         int b2 = trans_ncbi4na_to_blastna[a2];
  259.         
  260.         translated[i] = (b1 << 4) | b2;
  261.     }
  262.     
  263.     return translated;
  264. }
  265. static void
  266. s_SeqDBMapNcbiNA4ToBlastNA4(vector<char> & buf)
  267. {
  268.     static vector<Uint1> trans = s_SeqDBMapNcbiNA4ToBlastNA4Setup();
  269.     
  270.     for(Uint4 i = 0; i < buf.size(); i++) {
  271.         buf[i] = trans[ unsigned(buf[i]) & 0xFF ];
  272.     }
  273. }
  274. #endif
  275. static void
  276. s_SeqDBMapNcbiNA8ToBlastNA8(vector<char> & buf)
  277. {
  278.     Uint1 trans_ncbina8_to_blastna8[] = {
  279.         15, /* Gap, 0 */
  280.         0,  /* A,   1 */
  281.         1,  /* C,   2 */
  282.         6,  /* M,   3 */
  283.         2,  /* G,   4 */
  284.         4,  /* R,   5 */
  285.         9,  /* S,   6 */
  286.         13, /* V,   7 */
  287.         3,  /* T,   8 */
  288.         8,  /* W,   9 */
  289.         5,  /* Y,  10 */
  290.         12, /* H,  11 */
  291.         7,  /* K,  12 */
  292.         11, /* D,  13 */
  293.         10, /* B,  14 */
  294.         14  /* N,  15 */
  295.     };
  296.     
  297.     for(Uint4 i = 0; i < buf.size(); i++) {
  298.         buf[i] = trans_ncbina8_to_blastna8[ buf[i] ];
  299.     }
  300. }
  301. //--------------------
  302. // NEW (long) version
  303. //--------------------
  304. inline Uint4 s_ResLenNew(const vector<Int4> & ambchars, Uint4 i)
  305. {
  306.     return (ambchars[i] >> 16) & 0xFFF;
  307. }
  308. inline Uint4 s_ResPosNew(const vector<Int4> & ambchars, Uint4 i)
  309. {
  310.     return ambchars[i+1];
  311. }
  312. //-----------------------
  313. // OLD (compact) version
  314. //-----------------------
  315. inline Uint4 s_ResVal(const vector<Int4> & ambchars, Uint4 i)
  316. {
  317.     return (ambchars[i] >> 28);
  318. }
  319. inline Uint4 s_ResLenOld(const vector<Int4> & ambchars, Uint4 i)
  320. {
  321.     return (ambchars[i] >> 24) & 0xF;
  322. }
  323. inline Uint4 s_ResPosOld(const vector<Int4> & ambchars, Uint4 i)
  324. {
  325.     return ambchars[i];
  326. }
  327. static bool
  328. s_SeqDBRebuildDNA_NA4(vector<char>       & buf4bit,
  329.                       const vector<Int4> & amb_chars)
  330. {
  331.     if (buf4bit.empty())
  332.         return false;
  333.     
  334.     if (amb_chars.empty()) 
  335.         return true;
  336.     
  337.     Uint4 amb_num = amb_chars[0];
  338.     
  339.     /* Check if highest order bit set. */
  340.     bool new_format = (amb_num & 0x80000000) != 0;
  341.     
  342.     if (new_format) {
  343. amb_num &= 0x7FFFFFFF;
  344.     }
  345.     
  346.     for(Uint4 i=1; i < amb_num+1; i++) {
  347.         Int4  row_len  = 0;
  348.         Int4  position = 0;
  349.         Uint1 char_r   = 0;
  350.         
  351. if (new_format) {
  352.             char_r    = s_ResVal   (amb_chars, i);
  353.             row_len   = s_ResLenNew(amb_chars, i); 
  354.             position  = s_ResPosNew(amb_chars, i);
  355. } else {
  356.             char_r    = s_ResVal   (amb_chars, i);
  357.             row_len   = s_ResLenOld(amb_chars, i); 
  358.             position  = s_ResPosOld(amb_chars, i);
  359. }
  360.         
  361.         Int4  pos = position / 2;
  362.         Int4  rem = position & 1;  /* 0 or 1 */
  363.         Uint1 char_l = char_r << 4;
  364.         
  365.         Int4 j;
  366.         Int4 index = pos;
  367.         
  368.         // This could be made slightly faster for long runs.
  369.         
  370.         for(j = 0; j <= row_len; j++) {
  371.             if (!rem) {
  372.             buf4bit[index] = (buf4bit[index] & 0x0F) + char_l;
  373.              rem = 1;
  374.             } else {
  375.             buf4bit[index] = (buf4bit[index] & 0xF0) + char_r;
  376.              rem = 0;
  377.                 index++;
  378.             }
  379.      }
  380.         
  381. if (new_format) /* for new format we have 8 bytes for each element. */
  382.             i++;
  383.     }
  384.     
  385.     return true;
  386. }
  387. static bool
  388. s_SeqDBRebuildDNA_NA8(vector<char>       & buf4bit,
  389.                       const vector<Int4> & amb_chars)
  390. {
  391.     if (buf4bit.empty())
  392.         return false;
  393.     
  394.     if (amb_chars.empty()) 
  395.         return true;
  396.     
  397.     Uint4 amb_num = amb_chars[0];
  398.     
  399.     /* Check if highest order bit set. */
  400.     bool new_format = (amb_num & 0x80000000) != 0;
  401.     
  402.     if (new_format) {
  403. amb_num &= 0x7FFFFFFF;
  404.     }
  405.     
  406.     for(Uint4 i = 1; i < amb_num+1; i++) {
  407.         Int4  row_len  = 0;
  408.         Int4  position = 0;
  409.         Uint1 trans_ch = 0;
  410.         
  411. if (new_format) {
  412.             trans_ch  = s_ResVal   (amb_chars, i);
  413.             row_len   = s_ResLenNew(amb_chars, i); 
  414.             position  = s_ResPosNew(amb_chars, i);
  415. } else {
  416.             trans_ch  = s_ResVal   (amb_chars, i);
  417.             row_len   = s_ResLenOld(amb_chars, i); 
  418.             position  = s_ResPosOld(amb_chars, i);
  419. }
  420.         
  421.         Int4 index = position;
  422.         
  423.         // This could be made slightly faster for long runs.
  424.         
  425.         for(Int4 j = 0; j <= row_len; j++) {
  426.             buf4bit[index++] = trans_ch;
  427. //             if (!rem) {
  428. //             buf4bit[index] = (buf4bit[index] & 0x0F) + char_l;
  429. //              rem = 1;
  430. //             } else {
  431. //             buf4bit[index] = (buf4bit[index] & 0xF0) + char_r;
  432. //              rem = 0;
  433. //                 index++;
  434. //             }
  435.      }
  436.         
  437. if (new_format) /* for new format we have 8 bytes for each element. */
  438.             i++;
  439.     }
  440.     
  441.     return true;
  442. }
  443. static void
  444. s_SeqDBWriteSeqDataProt(CSeq_inst  & seqinst,
  445.                         const char * seq_buffer,
  446.                         Int4         length)
  447. {
  448.     // stuff - ncbistdaa
  449.     // mol = aa
  450.         
  451.     // This possibly/probably copies several times.
  452.     // 1. One copy into stdaa_data.
  453.     // 2. Second copy into NCBIstdaa.
  454.     // 3. Third copy into seqdata.
  455.     
  456.     vector<char> aa_data;
  457.     aa_data.resize(length);
  458.     
  459.     for(int i = 0; i < length; i++) {
  460.         aa_data[i] = seq_buffer[i];
  461.     }
  462.     
  463.     seqinst.SetSeq_data().SetNcbistdaa().Set().swap(aa_data);
  464.     seqinst.SetMol(CSeq_inst::eMol_aa);
  465. }
  466. static void
  467. s_SeqDBWriteSeqDataNucl(CSeq_inst    & seqinst,
  468.                         const char   * seq_buffer,
  469.                         Int4           length)
  470. {
  471.     Int4 whole_bytes  = length / 4;
  472.     Int4 partial_byte = ((length & 0x3) != 0) ? 1 : 0;
  473.     
  474.     vector<char> na_data;
  475.     na_data.resize(whole_bytes + partial_byte);
  476.     
  477.     for(int i = 0; i<whole_bytes; i++) {
  478.         na_data[i] = seq_buffer[i];
  479.     }
  480.     
  481.     if (partial_byte) {
  482.         na_data[whole_bytes] = seq_buffer[whole_bytes] & (0xFF - 0x03);
  483.     }
  484.     
  485.     seqinst.SetSeq_data().SetNcbi2na().Set().swap(na_data);
  486.     seqinst.SetMol(CSeq_inst::eMol_na);
  487. }
  488. static void
  489. s_SeqDBWriteSeqDataNucl(CSeq_inst    & seqinst,
  490.                         const char   * seq_buffer,
  491.                         Int4           length,
  492.                         vector<Int4> & amb_chars)
  493. {
  494.     vector<char> buffer_4na;
  495.     s_SeqDBMapNA2ToNA4(seq_buffer, buffer_4na, length); // length is not /4 here
  496.     s_SeqDBRebuildDNA_NA4(buffer_4na, amb_chars);
  497.     
  498.     seqinst.SetSeq_data().SetNcbi4na().Set().swap(buffer_4na);
  499.     seqinst.SetMol(CSeq_inst::eMol_na);
  500. }
  501. void s_GetDescrFromDefline(CRef<CBlast_def_line_set> deflines, string & descr)
  502. {
  503.     descr.erase();
  504.     
  505.     string seqid_str;
  506.     
  507.     typedef list< CRef<CBlast_def_line> >::const_iterator TDefIt; 
  508.     typedef list< CRef<CSeq_id        > >::const_iterator TSeqIt;
  509.    
  510.     const list< CRef<CBlast_def_line> > & dl = deflines->Get();
  511.     
  512.     for(TDefIt iter = dl.begin(); iter != dl.end(); iter++) {
  513.         ostringstream oss;
  514.         
  515.         const CBlast_def_line & defline = **iter;
  516.         
  517.         if (! descr.empty()) {
  518.             //oss << "1";
  519.             oss << " ";
  520.         }
  521.         
  522.         if (defline.CanGetSeqid()) {
  523.             const list< CRef<CSeq_id > > & sl = defline.GetSeqid();
  524.             
  525.             for (TSeqIt seqit = sl.begin(); seqit != sl.end(); seqit++) {
  526.                 (*seqit)->WriteAsFasta(oss);
  527.             }
  528.         }
  529.         
  530.         if (defline.CanGetTitle()) {
  531.             oss << defline.GetTitle();
  532.         }
  533.         
  534.         descr += oss.str();
  535.     }
  536. }
  537. CRef<CBioseq>
  538. CSeqDBVol::GetBioseq(Int4 oid,
  539.                      bool /*use_objmgr,*/,
  540.                      bool /*insert_ctrlA*/) const
  541. {
  542.     // 1. Declare variables.
  543.     
  544.     CRef<CBioseq> null_result;
  545.     
  546.     // 2. if we can't find the seq_num (get_link), we are done.
  547.     
  548.     //xx  Not relevant - the layer above this would do that before
  549.     //xx  This specific 'CSeqDB' object was involved.
  550.     
  551.     // 3. get the descriptor - i.e. sip, defline.  Probably this
  552.     // is like the function above that gets asn, but split it up
  553.     // more when returning it.
  554.     
  555.     // QUESTIONS: What do we actually want?  The defline & seqid, or
  556.     // the defline set and seqid set?  From readdb.c it looks like the
  557.     // single items are the prized artifacts.
  558.     
  559.     CRef<CBlast_def_line_set> defline_set(x_GetHdr(oid));
  560.     CRef<CBlast_def_line>     defline;
  561.     list< CRef< CSeq_id > >   seqids;
  562.     
  563.     {
  564.         if (defline_set.Empty() ||
  565.             (! defline_set->CanGet())) {
  566.             return null_result;
  567.         }
  568.         
  569.     
  570.         defline = defline_set->Get().front();
  571.         
  572.         if (! defline->CanGetSeqid()) {
  573.             // Not sure if this is necessary - if it turns out we can
  574.             // handle a null, this should be taken back out.
  575.             return null_result;
  576.         }
  577.         
  578.         // Do we want the list, or just the first CRef<>??  For now, get
  579.         // the whole list.
  580.         
  581.         seqids = defline->GetSeqid();
  582.     }
  583.     
  584.     // 4. If insert_ctrlA is FALSE, we convert each "^A" to " >";
  585.     // Otherwise, we just copy the defline across. (inline func?)
  586.     
  587.     //xx Ignoring ctrl-A issue for now (as per Tom's insns.)
  588.     
  589.     // 5. Get length & sequence (_get_sequence).  That should be
  590.     // mimicked before this.
  591.     
  592.     const char * seq_buffer = 0;
  593.     
  594.     Int4 length = x_GetSequence(oid, & seq_buffer);
  595.     
  596.     if (length < 1) {
  597.         return null_result;
  598.     }
  599.     
  600.     // 6. If using obj mgr, BioseqNew() is called; otherwise
  601.     // MemNew().  --> This is the BioseqPtr, bsp.
  602.     
  603.     //byte_store = BSNew(0);
  604.     
  605.     // 7. A byte store is created (BSNew()).
  606.     
  607.     //xx No allocation is done; instead we just call *Set() etc.
  608.     
  609.     // 8. If protein, we set bsp->mol = Seq_mol_aa, seq_data_type
  610.     // = Seq_code_ncbistdaa; then we write the buffer into the
  611.     // byte store.
  612.     
  613.     // 9. Nucleotide sequences require more pain, suffering.
  614.     // a. Try to get ambchars
  615.     // b. If there are any, convert sequence to 4 byte rep.
  616.     // c. Otherwise write to a byte store.
  617.     // d. Set mol = Seq_mol_na;
  618.     
  619.     // 10. Stick the byte store into the bsp->seq_data
  620.     
  621.     CRef<CBioseq> bioseq(new CBioseq);
  622.     
  623.     CSeq_inst & seqinst = bioseq->SetInst();
  624.     //CSeq_data & seqdata = seqinst->SetSeq_data();
  625.     
  626.     bool is_prot = (x_GetSeqType() == kSeqTypeProt);
  627.     
  628.     if (is_prot) {
  629.         s_SeqDBWriteSeqDataProt(seqinst, seq_buffer, length);
  630.     } else {
  631.         // nucl
  632.         vector<Int4> ambchars;
  633.         
  634.         if (! x_GetAmbChar(oid, ambchars)) {
  635.             return null_result;
  636.         }
  637.         
  638.         if (ambchars.empty()) {
  639.             // keep as 2 bit
  640.             s_SeqDBWriteSeqDataNucl(seqinst, seq_buffer, length);
  641.         } else {
  642.             // translate to 4 bit
  643.             s_SeqDBWriteSeqDataNucl(seqinst, seq_buffer, length, ambchars);
  644.         }
  645.         
  646.         // mol = na
  647.         seqinst.SetMol(CSeq_inst::eMol_na);
  648.     }
  649.     
  650.     if (seq_buffer) {
  651.         m_MemPool.Free((void*) seq_buffer);
  652.         seq_buffer = 0;
  653.     }
  654.     
  655.     // 11. Set the length, id (Seq_id), and repr (== raw).
  656.     
  657.     seqinst.SetLength(length);
  658.     seqinst.SetRepr(CSeq_inst::eRepr_raw);
  659.     bioseq->SetId().swap(seqids);
  660.     
  661.     // 12. Add the new_defline to the list at bsp->descr if
  662.     // non-null, with ValNodeAddString().
  663.     
  664.     // 13. If the format is not text (si), we get the defline and
  665.     // chain it onto the bsp->desc list; then we read and append
  666.     // taxonomy names to the list (readdb_get_taxonomy_names()).
  667.     
  668.     if (defline_set.NotEmpty()) {
  669.         // Convert defline to ... string.
  670.         
  671.         //1. Have a defline.. maybe.  Want to add this as the title.(?)
  672.         // A. How to add a description item:
  673.         
  674.         string description;
  675.         
  676.         s_GetDescrFromDefline(defline_set, description);
  677.         
  678.         CRef<CSeqdesc> desc1(new CSeqdesc);
  679.         desc1->SetTitle().swap(description);
  680.         
  681.         CSeq_descr & seqdesc = bioseq->SetDescr();
  682.         seqdesc.Set().push_back(desc1);
  683.     }
  684.     
  685.     // I'm going to let the taxonomy slide for now....
  686.     
  687.     //cerr << "Taxonomy, etc." << endl;
  688.     // 14. Return the bsp.
  689.     
  690.     // Everything seems eerily quiet so far, so...
  691.     
  692.     return bioseq;
  693. }
  694. Int4 CSeqDBVol::GetSequence(Int4 oid, const char ** buffer) const
  695. {
  696.     return x_GetSequence(oid, buffer);
  697. }
  698. char * CSeqDBVol::x_AllocType(Uint4 length, ESeqDBAllocType alloc_type) const
  699. {
  700.     // Specifying an allocation type of zero, uses the memory pool to
  701.     // do the allocation.  This is not intended to be visible to the
  702.     // end user, so it is not enumerated in seqdbcommon.hpp.
  703.     
  704.     char * retval = 0;
  705.     
  706.     switch(alloc_type) {
  707.     case eMalloc:
  708.         retval = (char*) malloc(length);
  709.         break;
  710.         
  711. // MemNew is not available yet.
  712. //     case eMemNew:
  713. //         retval = (char*) MemNew(length);
  714. //         break;
  715.         
  716.     case eNew:
  717.         retval = new char[length];
  718.         break;
  719.         
  720.     default:
  721.         retval = (char*) m_MemPool.Alloc(length);
  722.     }
  723.     
  724.     return retval;
  725. }
  726. Int4 CSeqDBVol::GetAmbigSeq(Int4            oid,
  727.                             char         ** buffer,
  728.                             Uint4           nucl_code,
  729.                             ESeqDBAllocType alloc_type) const
  730. {
  731.     char * buf1 = 0;
  732.     Int4 baselen = x_GetAmbigSeq(oid, & buf1, nucl_code, alloc_type);
  733.     
  734.     *buffer = buf1;
  735.     return baselen;
  736. }
  737. Int4 CSeqDBVol::x_GetAmbigSeq(Int4            oid,
  738.                               char         ** buffer,
  739.                               Uint4           nucl_code,
  740.                               ESeqDBAllocType alloc_type) const
  741. {
  742.     Int4 base_length = -1;
  743.     
  744.     if (kSeqTypeProt == m_Idx.GetSeqType()) {
  745.         const char * buf2 = 0;
  746.         
  747.         base_length = x_GetSequence(oid, & buf2);
  748.         
  749.         if (alloc_type == ESeqDBAllocType(0)) {
  750.             *buffer = (char*) buf2;
  751.         } else {
  752.             char * obj = x_AllocType(base_length, alloc_type);
  753.             
  754.             memcpy(obj, buf2, base_length);
  755.             m_MemPool.Free((void*) buf2);
  756.             
  757.             *buffer = obj;
  758.         }
  759.     } else {
  760.         vector<char> buffer_na8;
  761.         
  762.         {
  763.             // The code in this block is a few excerpts from
  764.             // GetBioseq() and s_SeqDBWriteSeqDataNucl().
  765.             
  766.             // Get the length and the (probably mmapped) data.
  767.             
  768.             const char * seq_buffer = 0;
  769.             
  770.             base_length = x_GetSequence(oid, & seq_buffer);
  771.             
  772.             if (base_length < 1) {
  773.                 NCBI_THROW(CSeqDBException, eFileErr,
  774.                            "Error: could not get sequence.");
  775.             }
  776.             
  777.             // Get ambiguity characters.
  778.             
  779.             vector<Int4> ambchars;
  780.             
  781.             if (! x_GetAmbChar(oid, ambchars) ) {
  782.                 NCBI_THROW(CSeqDBException, eFileErr,
  783.                            "File error: could not get ambiguity data.");
  784.             }
  785.             
  786.             // Combine and translate to 4 bits-per-character encoding.
  787.             
  788.             bool sentinel = (nucl_code == kSeqDBNuclBlastNA8);
  789.             
  790.             s_SeqDBMapNA2ToNA8(seq_buffer, buffer_na8, base_length, sentinel);
  791.             s_SeqDBRebuildDNA_NA8(buffer_na8, ambchars);
  792.             
  793.             if (sentinel) {
  794.                 // Translate bytewise, in place.
  795.                 s_SeqDBMapNcbiNA8ToBlastNA8(buffer_na8);
  796.             }
  797.             
  798.             // Return probably-mmapped sequence
  799.             
  800.             m_MemPool.Free((void*) seq_buffer);
  801.         }
  802.         
  803.         // NOTE:!! This is a memory leak; this is known, and I am
  804.         // fixing it, but the fix involves reorganization of code, and
  805.         // I don't want to bundle any more in this checkin. (kmb)
  806.         
  807.         int bytelen = buffer_na8.size();
  808.         char * uncomp_buf = x_AllocType(bytelen, alloc_type);
  809.         
  810.         for(int i = 0; i < bytelen; i++) {
  811.             uncomp_buf[i] = buffer_na8[i];
  812.         }
  813.         
  814.         *buffer = uncomp_buf;
  815.     }
  816.     
  817.     return base_length;
  818. }
  819. Int4 CSeqDBVol::x_GetSequence(Int4 oid, const char ** buffer) const
  820. {
  821.     Uint4 start_offset = 0;
  822.     Uint4 end_offset   = 0;
  823.         
  824.     Int4 length = -1;
  825.         
  826.     if (! m_Idx.GetSeqStartEnd(oid, start_offset, end_offset))
  827.         return -1;
  828.         
  829.     char seqtype = m_Idx.GetSeqType();
  830.         
  831.     if (kSeqTypeProt == seqtype) {
  832.         // Subtract one, for the inter-sequence null.
  833.                 
  834.         end_offset --;
  835.                 
  836.         length = end_offset - start_offset;
  837.             
  838.         *buffer = m_Seq.GetRegion(start_offset, end_offset);
  839.     } else if (kSeqTypeNucl == seqtype) {
  840.         // The last byte is partially full; the last two bits of
  841.         // the last byte store the number of nucleotides in the
  842.         // last byte (0 to 3).
  843.             
  844.         *buffer = m_Seq.GetRegion(start_offset, end_offset);
  845.             
  846.         Int4 whole_bytes = end_offset - start_offset - 1;
  847.             
  848.         char last_char = (*buffer)[whole_bytes];
  849.         Int4 remainder = last_char & 3;
  850.         length = (whole_bytes * 4) + remainder;
  851.     }
  852.         
  853.     return length;
  854. }
  855. list< CRef<CSeq_id> > CSeqDBVol::GetSeqIDs(Uint4 oid) const
  856. {
  857.     list< CRef< CSeq_id > > seqids;
  858.     
  859.     CRef<CBlast_def_line_set> defline_set(x_GetHdr(oid));
  860.     
  861.     if ((! defline_set.Empty()) && defline_set->CanGet()) {
  862.         CRef<CBlast_def_line> defline = defline_set->Get().front();
  863.         
  864.         if (defline->CanGetSeqid()) {
  865.             seqids = defline->GetSeqid();
  866.         }
  867.     }
  868.     
  869.     return seqids;
  870. }
  871. Uint8 CSeqDBVol::GetTotalLength(void) const
  872. {
  873.     return m_Idx.GetTotalLength();
  874. }
  875. CRef<CBlast_def_line_set> CSeqDBVol::GetHdr(Uint4 oid) const
  876. {
  877.     return x_GetHdr(oid);
  878. }
  879. CRef<CBlast_def_line_set> CSeqDBVol::x_GetHdr(Uint4 oid) const
  880. {
  881.     CRef<CBlast_def_line_set> nullret;
  882.         
  883.     Uint4 hdr_start = 0;
  884.     Uint4 hdr_end   = 0;
  885.         
  886.     if (! m_Idx.GetHdrStartEnd(oid, hdr_start, hdr_end)) {
  887.         return nullret;
  888.     }
  889.     
  890.     const char * asn_region = m_Hdr.GetRegion(hdr_start, hdr_end);
  891.     
  892.     // Now; create an ASN.1 object from the memory chunk provided
  893.     // here.
  894.         
  895.     if (! asn_region) {
  896.         return nullret;
  897.     }
  898.     
  899.     // Get the data as a string, then as a stringstream, then build
  900.     // the actual asn.1 object.  How much 'extra' work is done here?
  901.     // Perhaps a dedicated ASN.1 memory-stream object would be of some
  902.     // benefit, particularly in the "called 100000 times" cases.
  903.     
  904.     istringstream asndata( string(asn_region, asn_region + (hdr_end - hdr_start)) );
  905.     
  906.     m_MemPool.Free((void*) asn_region);
  907.     
  908.     auto_ptr<CObjectIStream> inpstr(CObjectIStream::Open(eSerial_AsnBinary, asndata));
  909.     
  910.     CRef<objects::CBlast_def_line_set> phil(new objects::CBlast_def_line_set);
  911.     
  912.     *inpstr >> *phil;
  913.     
  914.     
  915.     return phil;
  916. }
  917. bool CSeqDBVol::x_GetAmbChar(Uint4 oid, vector<Int4> ambchars) const
  918. {
  919.     Uint4 start_offset = 0;
  920.     Uint4 end_offset   = 0;
  921.     
  922.     bool ok = m_Idx.GetAmbStartEnd(oid, start_offset, end_offset);
  923.     
  924.     if (! ok) {
  925.         return false;
  926.     }
  927.     
  928.     Int4 length = end_offset - start_offset;
  929.     
  930.     if (0 == length)
  931.         return true;
  932.     
  933.     Int4 total = length / 4;
  934.     
  935.     Int4 * buffer = (Int4*) m_Seq.GetRegion(start_offset, start_offset + (total * 4));
  936.     
  937.     // This makes no sense...
  938.     total &= 0x7FFFFFFF;
  939.     
  940.     ambchars.resize(total);
  941.     
  942.     for(int i = 0; i<total; i++) {
  943. //ambchars[i] = CByteSwap::GetInt4((const unsigned char *)(& buffer[i]));
  944. ambchars[i] = SeqDB_GetStdOrd((const unsigned char *)(& buffer[i]));
  945.     }
  946.     
  947.     m_MemPool.Free((void*) buffer);
  948.     
  949.     return true;
  950. }
  951. Uint4 CSeqDBVol::GetNumSeqs(void) const
  952. {
  953.     return m_Idx.GetNumSeqs();
  954. }
  955. string CSeqDBVol::GetTitle(void) const
  956. {
  957.     return m_Idx.GetTitle();
  958. }
  959. string CSeqDBVol::GetDate(void) const
  960. {
  961.     return m_Idx.GetDate();
  962. }
  963. Uint4 CSeqDBVol::GetMaxLength(void) const
  964. {
  965.     return m_Idx.GetMaxLength();
  966. }
  967. END_NCBI_SCOPE