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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: blast_setup_cxx.cpp,v $
  4.  * PRODUCTION Revision 1000.7  2004/06/01 18:05:58  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.68
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: blast_setup_cxx.cpp,v 1000.7 2004/06/01 18:05:58 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:  Christiam Camacho
  35. *
  36. * ===========================================================================
  37. */
  38. /// @file blast_setup_cxx.cpp
  39. /// Auxiliary setup functions for Blast objects interface.
  40. #include <ncbi_pch.hpp>
  41. #include <corelib/ncbiapp.hpp>
  42. #include <corelib/ncbireg.hpp>
  43. #include <corelib/metareg.hpp>
  44. #include <corelib/ncbifile.hpp>
  45. #include <objmgr/object_manager.hpp>
  46. #include <objmgr/scope.hpp>
  47. #include <objmgr/seq_vector.hpp>
  48. #include <objmgr/util/sequence.hpp>
  49. #include <objects/seqloc/Seq_loc.hpp>
  50. #include <objects/seq/seqport_util.hpp>
  51. #include <objects/seqfeat/Genetic_code_table.hpp>
  52. #include <objects/seq/Seq_data.hpp>
  53. #include <objects/seq/NCBIstdaa.hpp>
  54. #include <algo/blast/api/blast_options.hpp>
  55. #include "blast_setup.hpp"
  56. #include <algo/blast/core/blast_util.h>
  57. #include <algo/blast/core/blast_encoding.h>
  58. #include <algorithm>
  59. /** @addtogroup AlgoBlast
  60.  *
  61.  * @{
  62.  */
  63. BEGIN_NCBI_SCOPE
  64. BEGIN_SCOPE(blast)
  65. USING_SCOPE(ncbi::objects);
  66. /// Now allows query concatenation
  67. void
  68. SetupQueryInfo(const TSeqLocVector& queries, const CBlastOptions& options, 
  69.                BlastQueryInfo** qinfo)
  70. {
  71.     ASSERT(qinfo);
  72.     // Allocate and initialize the query info structure
  73.     if ( !((*qinfo) = (BlastQueryInfo*) calloc(1, sizeof(BlastQueryInfo)))) {
  74.         NCBI_THROW(CBlastException, eOutOfMemory, "Query info");
  75.     }
  76.     EProgram prog = options.GetProgram();
  77.     unsigned int nframes = GetNumberOfFrames(prog);
  78.     (*qinfo)->num_queries = static_cast<int>(queries.size());
  79.     (*qinfo)->first_context = 0;
  80.     (*qinfo)->last_context = (*qinfo)->num_queries * nframes - 1;
  81.     // Allocate the various arrays of the query info structure
  82.     int* context_offsets = NULL;
  83.     if ( !(context_offsets = (int*)
  84.            malloc(sizeof(int) * ((*qinfo)->last_context + 2)))) {
  85.         NCBI_THROW(CBlastException, eOutOfMemory, "Context offsets array");
  86.     }
  87.     if ( !((*qinfo)->eff_searchsp_array = 
  88.            (Int8*) calloc((*qinfo)->last_context + 1, sizeof(Int8)))) {
  89.         NCBI_THROW(CBlastException, eOutOfMemory, "Search space array");
  90.     }
  91.     if ( !((*qinfo)->length_adjustments = 
  92.            (int*) calloc((*qinfo)->last_context + 1, sizeof(int)))) {
  93.         NCBI_THROW(CBlastException, eOutOfMemory, "Length adjustments array");
  94.     }
  95.     (*qinfo)->context_offsets = context_offsets;
  96.     context_offsets[0] = 0;
  97.     bool is_na = (prog == eBlastn) ? true : false;
  98.     bool translate = 
  99.         ((prog == eBlastx) || (prog == eTblastx)) ? true : false;
  100.     // Adjust first context depending on the first query strand
  101.     // Unless the strand option is set to single strand, the actual
  102.     // CSeq_locs dictate which strand to examine during the search.
  103.     ENa_strand strand_opt = options.GetStrandOption();
  104.     ENa_strand strand;
  105.     if (is_na || translate) {
  106.         if (strand_opt == eNa_strand_both || 
  107.             strand_opt == eNa_strand_unknown) {
  108.             strand = sequence::GetStrand(*queries.front().seqloc, 
  109.                                          queries.front().scope);
  110.         } else {
  111.             strand = strand_opt;
  112.         }
  113.         if (strand == eNa_strand_minus) {
  114.             if (translate) {
  115.                 (*qinfo)->first_context = 3;
  116.             } else {
  117.                 (*qinfo)->first_context = 1;
  118.             }
  119.         }
  120.     }
  121.     // Set up the context offsets into the sequence that will be added
  122.     // to the sequence block structure.
  123.     unsigned int ctx_index = 0;      // index into context_offsets array
  124.     // Longest query length, to be saved in the query info structure
  125.     Uint4 max_length = 0;
  126.     ITERATE(TSeqLocVector, itr, queries) {
  127.         TSeqPos length = sequence::GetLength(*itr->seqloc, itr->scope);
  128.         ASSERT(length != numeric_limits<TSeqPos>::max());
  129.         strand = sequence::GetStrand(*itr->seqloc, itr->scope);
  130.         if (strand_opt == eNa_strand_minus || strand_opt == eNa_strand_plus) {
  131.             strand = strand_opt;
  132.         }
  133.         if (translate) {
  134.             for (unsigned int i = 0; i < nframes; i++) {
  135.                 unsigned int prot_length = 
  136.                     (length - i % CODON_LENGTH) / CODON_LENGTH;
  137.                 max_length = MAX(max_length, prot_length);
  138.                 switch (strand) {
  139.                 case eNa_strand_plus:
  140.                     if (i < 3) {
  141.                         context_offsets[ctx_index + i + 1] = 
  142.                             context_offsets[ctx_index + i] + prot_length + 1;
  143.                     } else {
  144.                         context_offsets[ctx_index + i + 1] = 
  145.                             context_offsets[ctx_index + i];
  146.                     }
  147.                     break;
  148.                 case eNa_strand_minus:
  149.                     if (i < 3) {
  150.                         context_offsets[ctx_index + i + 1] = 
  151.                             context_offsets[ctx_index + i];
  152.                     } else {
  153.                         context_offsets[ctx_index + i + 1] =
  154.                             context_offsets[ctx_index + i] + prot_length + 1;
  155.                     }
  156.                     break;
  157.                 case eNa_strand_both:
  158.                 case eNa_strand_unknown:
  159.                     context_offsets[ctx_index + i + 1] = 
  160.                         context_offsets[ctx_index + i] + prot_length + 1;
  161.                     break;
  162.                 default:
  163.                     abort();
  164.                 }
  165.             }
  166.         } else {
  167.             max_length = MAX(max_length, length);
  168.             if (is_na) {
  169.                 switch (strand) {
  170.                 case eNa_strand_plus:
  171.                     context_offsets[ctx_index + 1] =
  172.                         context_offsets[ctx_index] + length + 1;
  173.                     context_offsets[ctx_index + 2] =
  174.                         context_offsets[ctx_index + 1];
  175.                     break;
  176.                 case eNa_strand_minus:
  177.                     context_offsets[ctx_index + 1] =
  178.                         context_offsets[ctx_index];
  179.                     context_offsets[ctx_index + 2] =
  180.                         context_offsets[ctx_index + 1] + length + 1;
  181.                     break;
  182.                 case eNa_strand_both:
  183.                 case eNa_strand_unknown:
  184.                     context_offsets[ctx_index + 1] =
  185.                         context_offsets[ctx_index] + length + 1;
  186.                     context_offsets[ctx_index + 2] =
  187.                         context_offsets[ctx_index + 1] + length + 1;
  188.                     break;
  189.                 default:
  190.                     abort();
  191.                 }
  192.             } else {    // protein
  193.                 context_offsets[ctx_index + 1] = 
  194.                     context_offsets[ctx_index] + length + 1;
  195.             }
  196.         }
  197.         ctx_index += nframes;
  198.     }
  199.     (*qinfo)->max_length = max_length;
  200. }
  201. Uint1
  202. GetQueryEncoding(EProgram program)
  203. {
  204.     Uint1 retval = 0;
  205.     switch (program) {
  206.     case eBlastn: 
  207.         retval = BLASTNA_ENCODING; 
  208.         break;
  209.     case eBlastp: 
  210.     case eTblastn:
  211.     case eRPSBlast: 
  212.         retval = BLASTP_ENCODING; 
  213.         break;
  214.     case eBlastx:
  215.     case eTblastx:
  216.     case eRPSTblastn:
  217.         retval = NCBI4NA_ENCODING;
  218.         break;
  219.     default:
  220.         NCBI_THROW(CBlastException, eBadParameter, "Query Encoding");
  221.     }
  222.     return retval;
  223. }
  224. Uint1
  225. GetSubjectEncoding(EProgram program)
  226. {
  227.     Uint1 retval = 0;
  228.     switch (program) {
  229.     case eBlastn: 
  230.         retval = BLASTNA_ENCODING; 
  231.         break;
  232.     case eBlastp: 
  233.     case eBlastx:
  234.         retval = BLASTP_ENCODING; 
  235.         break;
  236.     case eTblastn:
  237.     case eTblastx:
  238.         retval = NCBI4NA_ENCODING;
  239.         break;
  240.     default:
  241.         NCBI_THROW(CBlastException, eBadParameter, "Subject Encoding");
  242.     }
  243.     return retval;
  244. }
  245. void
  246. SetupQueries(const TSeqLocVector& queries, const CBlastOptions& options,
  247.              const CBlastQueryInfo& qinfo, BLAST_SequenceBlk** seqblk)
  248. {
  249.     ASSERT(seqblk);
  250.     ASSERT(queries.size() != 0);
  251.     EProgram prog = options.GetProgram();
  252.     // Determine sequence encoding
  253.     Uint1 encoding = GetQueryEncoding(prog);
  254.     int buflen = qinfo->context_offsets[qinfo->last_context+1] + 1;
  255.     Uint1* buf = (Uint1*) calloc((buflen+1), sizeof(Uint1));
  256.     if ( !buf ) {
  257.         NCBI_THROW(CBlastException, eOutOfMemory, "Query sequence buffer");
  258.     }
  259.     bool is_na = (prog == eBlastn) ? true : false;
  260.     bool translate = ((prog == eBlastx) || (prog == eTblastx)) ? true : false;
  261.     unsigned int ctx_index = 0;      // index into context_offsets array
  262.     unsigned int nframes = GetNumberOfFrames(prog);
  263.     BlastMaskLoc* mask = NULL, *head_mask = NULL, *last_mask = NULL;
  264.     // Unless the strand option is set to single strand, the actual
  265.     // CSeq_locs dictacte which strand to examine during the search
  266.     ENa_strand strand_opt = options.GetStrandOption();
  267.     int index = 0;
  268.     ITERATE(TSeqLocVector, itr, queries) {
  269.         ENa_strand strand;
  270.         if ((is_na || translate) &&
  271.             (strand_opt == eNa_strand_unknown || 
  272.              strand_opt == eNa_strand_both)) 
  273.         {
  274.             strand = sequence::GetStrand(*itr->seqloc, itr->scope);
  275.         } else {
  276.             strand = strand_opt;
  277.         }
  278.         if (itr->mask)
  279.             mask = CSeqLoc2BlastMaskLoc(*itr->mask, index);
  280.         ++index;
  281.         if (translate) {
  282.             ASSERT(strand == eNa_strand_both ||
  283.                    strand == eNa_strand_plus ||
  284.                    strand == eNa_strand_minus);
  285.             // Get both strands of the original nucleotide sequence with
  286.             // sentinels
  287.             pair<AutoPtr<Uint1, CDeleter<Uint1> >, TSeqPos> seqbuf(
  288.                 GetSequence(*itr->seqloc, encoding, itr->scope, strand,
  289.                             eSentinels));
  290.             
  291.             AutoPtr<Uint1, ArrayDeleter<Uint1> > gc = 
  292.                 FindGeneticCode(options.GetQueryGeneticCode());
  293.             int na_length = sequence::GetLength(*itr->seqloc, itr->scope);
  294.             Uint1* seqbuf_rev = NULL;  // negative strand
  295.             if (strand == eNa_strand_both)
  296.                seqbuf_rev = seqbuf.first.get() + na_length + 1;
  297.             else if (strand == eNa_strand_minus)
  298.                seqbuf_rev = seqbuf.first.get() + 1;
  299.             // Populate the sequence buffer
  300.             for (unsigned int i = 0; i < nframes; i++) {
  301.                 if (BLAST_GetQueryLength(qinfo, i) <= 0) {
  302.                     continue;
  303.                 }
  304.                 int offset = qinfo->context_offsets[ctx_index + i];
  305.                 short frame = BLAST_ContextToFrame(prog, i);
  306.                 BLAST_GetTranslation(seqbuf.first.get() + 1, seqbuf_rev,
  307.                    na_length, frame, &buf[offset], gc.get());
  308.             }
  309.             // Translate the lower case mask coordinates;
  310.             BlastMaskLocDNAToProtein(&mask, *itr->seqloc, itr->scope);
  311.         } else if (is_na) {
  312.             ASSERT(strand == eNa_strand_both ||
  313.                    strand == eNa_strand_plus ||
  314.                    strand == eNa_strand_minus);
  315.             pair<AutoPtr<Uint1, CDeleter<Uint1> >, TSeqPos> seqbuf(
  316.                 GetSequence(*itr->seqloc, encoding, itr->scope, strand,
  317.                             eSentinels));
  318.             int idx = (strand == eNa_strand_minus) ? 
  319.                 ctx_index + 1 : ctx_index;
  320.             int offset = qinfo->context_offsets[idx];
  321.             memcpy(&buf[offset], seqbuf.first.get(), seqbuf.second);
  322.         } else {
  323.             pair<AutoPtr<Uint1, CDeleter<Uint1> >, TSeqPos> seqbuf(
  324.                 GetSequence(*itr->seqloc, encoding, itr->scope,
  325.                             eNa_strand_unknown, eSentinels));
  326.             int offset = qinfo->context_offsets[ctx_index];
  327.             memcpy(&buf[offset], seqbuf.first.get(), seqbuf.second);
  328.         }
  329.         ctx_index += nframes;
  330.         
  331.         if (mask) {
  332.             if ( !last_mask )
  333.                 head_mask = last_mask = mask;
  334.             else {
  335.                 last_mask->next = mask;
  336.                 last_mask = last_mask->next;
  337.             }
  338.         }
  339.     }
  340.     if (BlastSeqBlkNew(seqblk) < 0) {
  341.         NCBI_THROW(CBlastException, eOutOfMemory, "Query sequence block");
  342.     }
  343.     BlastSeqBlkSetSequence(*seqblk, buf, buflen - 2);
  344.     (*seqblk)->lcase_mask = head_mask;
  345.     (*seqblk)->lcase_mask_allocated = TRUE;
  346.     return;
  347. }
  348. void
  349. SetupSubjects(const TSeqLocVector& subjects, 
  350.               EProgram prog,
  351.               vector<BLAST_SequenceBlk*>* seqblk_vec, 
  352.               unsigned int* max_subjlen)
  353. {
  354.     ASSERT(seqblk_vec);
  355.     ASSERT(max_subjlen);
  356.     ASSERT(subjects.size() != 0);
  357.     // Nucleotide subject sequences are stored in ncbi2na format, but the
  358.     // uncompressed format (ncbi4na/blastna) is also kept to re-evaluate with
  359.     // the ambiguities
  360.     bool subj_is_na = (prog == eBlastn  ||
  361.                        prog == eTblastn ||
  362.                        prog == eTblastx);
  363.     ESentinelType sentinels = eSentinels;
  364.     if (prog == eTblastn || prog == eTblastx) {
  365.         sentinels = eNoSentinels;
  366.     }
  367.     Uint1 encoding = GetSubjectEncoding(prog);
  368.        
  369.     // TODO: Should strand selection on the subject sequences be allowed?
  370.     //ENa_strand strand = options->GetStrandOption(); 
  371.     int index = 0; // Needed for lower case masks only.
  372.     *max_subjlen = 0;
  373.     ITERATE(TSeqLocVector, itr, subjects) {
  374.         BLAST_SequenceBlk* subj = NULL;
  375.         pair<AutoPtr<Uint1, CDeleter<Uint1> >, TSeqPos> seqbuf(
  376.             GetSequence(*itr->seqloc, encoding, itr->scope,
  377.                         eNa_strand_plus, sentinels));
  378.         if (BlastSeqBlkNew(&subj) < 0) {
  379.             NCBI_THROW(CBlastException, eOutOfMemory, "Subject sequence block");
  380.         }
  381.         /* Set the lower case mask, if it exists */
  382.         if (itr->mask)
  383.             subj->lcase_mask = CSeqLoc2BlastMaskLoc(*itr->mask, index);
  384.         ++index;
  385.         if (subj_is_na) {
  386.             BlastSeqBlkSetSequence(subj, seqbuf.first.release(), 
  387.                (sentinels == eSentinels) ? seqbuf.second - 2 : seqbuf.second);
  388.             try {
  389.                 // Get the compressed sequence
  390.                 pair<AutoPtr<Uint1, CDeleter<Uint1> >, TSeqPos> comp_seqbuf(
  391.                     GetSequence(*itr->seqloc, NCBI2NA_ENCODING, itr->scope,
  392.                                  eNa_strand_plus, eNoSentinels));
  393.                 BlastSeqBlkSetCompressedSequence(subj, 
  394.                                                  comp_seqbuf.first.release());
  395.             } catch (const CSeqVectorException&) {
  396.                 BlastSequenceBlkFree(subj);
  397.                 NCBI_THROW(CBlastException, eInvalidCharacter, 
  398.                            "Gaps found in subject sequence");
  399.             }
  400.         } else {
  401.             BlastSeqBlkSetSequence(subj, seqbuf.first.release(), 
  402.                                    seqbuf.second - 2);
  403.         }
  404.         seqblk_vec->push_back(subj);
  405.         (*max_subjlen) = MAX((*max_subjlen),
  406.                 sequence::GetLength(*itr->seqloc, itr->scope));
  407.     }
  408. }
  409. TSeqPos CalculateSeqBufferLength(TSeqPos sequence_length, Uint1 encoding,
  410.                                  ENa_strand strand, ESentinelType sentinel)
  411.                                  THROWS((CBlastException))
  412. {
  413.     TSeqPos retval = 0;
  414.     switch (encoding) {
  415.     // Strand and sentinels are irrelevant in this encoding.
  416.     // Strand is always plus and sentinels cannot be represented
  417.     case NCBI2NA_ENCODING:
  418.         ASSERT(sentinel == eNoSentinels);
  419.         ASSERT(strand == eNa_strand_plus);
  420.         retval = sequence_length / COMPRESSION_RATIO + 1;
  421.         break;
  422.     case NCBI4NA_ENCODING:
  423.         if (sentinel == eSentinels) {
  424.             if (strand == eNa_strand_both) {
  425.                 retval = sequence_length * 2;
  426.                 retval += 3;
  427.             } else {
  428.                 retval = sequence_length + 2;
  429.             }
  430.         } else {
  431.             if (strand == eNa_strand_both) {
  432.                 retval = sequence_length * 2;
  433.             } else {
  434.                 retval = sequence_length;
  435.             }
  436.         }
  437.         break;
  438.     case BLASTP_ENCODING:
  439.         ASSERT(sentinel == eSentinels);
  440.         ASSERT(strand == eNa_strand_unknown);
  441.         retval = sequence_length + 2;
  442.         break;
  443.     default:
  444.         NCBI_THROW(CBlastException, eBadParameter, "Unsupported encoding");
  445.     }
  446.     return retval;
  447. }
  448. // Compresses sequence data on vector to buffer, which should have been
  449. // allocated and have the right size.
  450. static 
  451. void CompressDNA(const CSeqVector& vec, Uint1* buffer, const int buflen)
  452. {
  453.     TSeqPos i;                  // loop index of original sequence
  454.     TSeqPos ci;                 // loop index for compressed sequence
  455.     ASSERT(vec.GetCoding() == CSeq_data::e_Ncbi2na);
  456.     for (ci = 0, i = 0; ci < (TSeqPos) buflen-1; ci++, i += COMPRESSION_RATIO) {
  457.         buffer[ci] = ((vec[i+0] & NCBI2NA_MASK)<<6) |
  458.                      ((vec[i+1] & NCBI2NA_MASK)<<4) |
  459.                      ((vec[i+2] & NCBI2NA_MASK)<<2) |
  460.                      ((vec[i+3] & NCBI2NA_MASK)<<0);
  461.     }
  462.     buffer[ci] = 0;
  463.     for (; i < vec.size(); i++) {
  464.             Uint1 bit_shift = 0;
  465.             switch (i%COMPRESSION_RATIO) {
  466.                case 0: bit_shift = 6; break;
  467.                case 1: bit_shift = 4; break;
  468.                case 2: bit_shift = 2; break;
  469.                default: abort();   // should never happen
  470.             }
  471.             buffer[ci] |= ((vec[i] & NCBI2NA_MASK)<<bit_shift);
  472.     }
  473.     // Set the number of bases in the last byte.
  474.     buffer[ci] |= vec.size()%COMPRESSION_RATIO;
  475. }
  476. Uint1 GetSentinelByte(Uint1 encoding) THROWS((CBlastException))
  477. {
  478.     switch (encoding) {
  479.     case BLASTP_ENCODING:
  480.         return NULLB;
  481.     case NCBI4NA_ENCODING:
  482.     case BLASTNA_ENCODING:
  483.         return 0xF;
  484.     default:
  485.         NCBI_THROW(CBlastException, eBadParameter, "Unsupported encoding");
  486.     }
  487. }
  488. pair<AutoPtr<Uint1, CDeleter<Uint1> >, TSeqPos>
  489. GetSequence(const CSeq_loc& sl, Uint1 encoding, CScope* scope,
  490.             ENa_strand strand, ESentinelType sentinel) 
  491.             THROWS((CBlastException, CException))
  492. {
  493.     Uint1* buf = NULL;          // buffer to write sequence
  494.     Uint1* buf_var = NULL;      // temporary pointer to buffer
  495.     TSeqPos buflen;             // length of buffer allocated
  496.     TSeqPos i;                  // loop index of original sequence
  497.     AutoPtr<Uint1, CDeleter<Uint1> > safe_buf; // contains buf to ensure 
  498.                                                // exception safety
  499.     CBioseq_Handle handle = scope->GetBioseqHandle(sl); // might throw exception
  500.     // Retrieves the correct strand (plus or minus), but not both
  501.     CSeqVector sv =
  502.         handle.GetSequenceView(sl, CBioseq_Handle::eViewConstructed,
  503.                                CBioseq_Handle::eCoding_Ncbi);
  504.     switch (encoding) {
  505.     // Protein sequences (query & subject) always have sentinels around sequence
  506.     case BLASTP_ENCODING:
  507.         sv.SetCoding(CSeq_data::e_Ncbistdaa);
  508.         buflen = CalculateSeqBufferLength(sv.size(), BLASTP_ENCODING);
  509.         buf = buf_var = (Uint1*) malloc(sizeof(Uint1)*buflen);
  510.         safe_buf.reset(buf);
  511.         *buf_var++ = GetSentinelByte(encoding);
  512.         for (i = 0; i < sv.size(); i++)
  513.             *buf_var++ = sv[i];
  514.         *buf_var++ = GetSentinelByte(encoding);
  515.         break;
  516.     case NCBI4NA_ENCODING:
  517.     case BLASTNA_ENCODING: // Used for nucleotide blastn queries
  518.         sv.SetCoding(CSeq_data::e_Ncbi4na);
  519.         buflen = CalculateSeqBufferLength(sv.size(), NCBI4NA_ENCODING,
  520.                                           strand, sentinel);
  521.         buf = buf_var = (Uint1*) malloc(sizeof(Uint1)*buflen);
  522.         safe_buf.reset(buf);
  523.         if (sentinel == eSentinels)
  524.             *buf_var++ = GetSentinelByte(encoding);
  525.         if (encoding == BLASTNA_ENCODING) {
  526.             for (i = 0; i < sv.size(); i++) {
  527.                 *buf_var++ = NCBI4NA_TO_BLASTNA[sv[i]];
  528.             }
  529.         } else {
  530.             for (i = 0; i < sv.size(); i++) {
  531.                 *buf_var++ = sv[i];
  532.             }
  533.         }
  534.         if (sentinel == eSentinels)
  535.             *buf_var++ = GetSentinelByte(encoding);
  536.         if (strand == eNa_strand_both) {
  537.             // Get the minus strand if both strands are required
  538.             sv = handle.GetSequenceView(sl, CBioseq_Handle::eViewConstructed,
  539.                                         CBioseq_Handle::eCoding_Ncbi, 
  540.                                         eNa_strand_minus);
  541.             sv.SetCoding(CSeq_data::e_Ncbi4na);
  542.             if (encoding == BLASTNA_ENCODING) {
  543.                 for (i = 0; i < sv.size(); i++) {
  544.                     *buf_var++ = NCBI4NA_TO_BLASTNA[sv[i]];
  545.                 }
  546.             } else {
  547.                 for (i = 0; i < sv.size(); i++) {
  548.                     *buf_var++ = sv[i];
  549.                 }
  550.             }
  551.             if (sentinel == eSentinels) {
  552.                 *buf_var++ = GetSentinelByte(encoding);
  553.             }
  554.         }
  555.         break;
  556.     /* Used only in Blast2Sequences for the subject sequence. 
  557.      * No sentinels can be used. As in readdb, remainder 
  558.      * (sv.size()%COMPRESSION_RATIO != 0) goes in the last 2 bits of the 
  559.      * last byte.
  560.      */
  561.     case NCBI2NA_ENCODING:
  562.         ASSERT(sentinel == eNoSentinels);
  563.         sv.SetCoding(CSeq_data::e_Ncbi2na);
  564.         buflen = CalculateSeqBufferLength(sv.size(), sv.GetCoding(),
  565.                                           eNa_strand_plus, eNoSentinels);
  566.         buf = (Uint1*) malloc(sizeof(Uint1)*buflen);
  567.         safe_buf.reset(buf);
  568.         CompressDNA(sv, buf, buflen);
  569.         break;
  570.     default:
  571.         NCBI_THROW(CBlastException, eBadParameter, "Invalid encoding");
  572.     }
  573.     return make_pair(safe_buf, buflen);
  574. }
  575. #if 0
  576. // Not used right now, need to complete implementation
  577. void
  578. BLASTGetTranslation(const Uint1* seq, const Uint1* seq_rev,
  579.         const int nucl_length, const short frame, Uint1* translation)
  580. {
  581.     TSeqPos ni = 0;     // index into nucleotide sequence
  582.     TSeqPos pi = 0;     // index into protein sequence
  583.     const Uint1* nucl_seq = frame >= 0 ? seq : seq_rev;
  584.     translation[0] = NULLB;
  585.     for (ni = ABS(frame)-1; ni < (TSeqPos) nucl_length-2; ni += CODON_LENGTH) {
  586.         Uint1 residue = CGen_code_table::CodonToIndex(nucl_seq[ni+0], 
  587.                                                       nucl_seq[ni+1],
  588.                                                       nucl_seq[ni+2]);
  589.         if (IS_residue(residue))
  590.             translation[pi++] = residue;
  591.     }
  592.     translation[pi++] = NULLB;
  593.     return;
  594. }
  595. #endif
  596. AutoPtr<Uint1, ArrayDeleter<Uint1> >
  597. FindGeneticCode(int genetic_code)
  598. {
  599.     Uint1* retval = NULL;
  600.     CSeq_data gc_ncbieaa(CGen_code_table::GetNcbieaa(genetic_code),
  601.             CSeq_data::e_Ncbieaa);
  602.     CSeq_data gc_ncbistdaa;
  603.     TSeqPos nconv = CSeqportUtil::Convert(gc_ncbieaa, &gc_ncbistdaa,
  604.             CSeq_data::e_Ncbistdaa);
  605.     ASSERT(gc_ncbistdaa.IsNcbistdaa());
  606.     ASSERT(nconv == gc_ncbistdaa.GetNcbistdaa().Get().size());
  607.     try {
  608.         retval = new Uint1[nconv];
  609.     } catch (const bad_alloc&) {
  610.         return NULL;
  611.     }
  612.     for (unsigned int i = 0; i < nconv; i++)
  613.         retval[i] = gc_ncbistdaa.GetNcbistdaa().Get()[i];
  614.     return retval;
  615. }
  616. string
  617. FindMatrixPath(const char* matrix_name, bool is_prot)
  618. {
  619.     string retval;
  620.     string full_path;       // full path to matrix file
  621.     if (!matrix_name)
  622.         return retval;
  623.     string mtx(matrix_name);
  624.     mtx = NStr::ToUpper(mtx);
  625.     // Look for matrix file in local directory
  626.     full_path = mtx;
  627.     if (CFile(full_path).Exists()) {
  628.         return retval;
  629.     }
  630.     // Obtain the matrix path from the ncbi configuration file
  631.     CMetaRegistry::SEntry sentry;
  632.     sentry = CMetaRegistry::Load("ncbi", CMetaRegistry::eName_RcOrIni);
  633.     string path = sentry.registry ? sentry.registry->Get("NCBI", "Data") : "";
  634.     full_path = CFile::MakePath(path, mtx);
  635.     if (CFile(full_path).Exists()) {
  636.         retval = full_path;
  637.         retval.erase(retval.size() - mtx.size());
  638.         return retval;
  639.     }
  640.     // Try appending "aa" or "nt" 
  641.     full_path = path;
  642.     full_path += CFile::AddTrailingPathSeparator(full_path);
  643.     full_path += is_prot ? "aa" : "nt";
  644.     full_path += CFile::AddTrailingPathSeparator(full_path);
  645.     full_path += mtx;
  646.     if (CFile(full_path).Exists()) {
  647.         retval = full_path;
  648.         retval.erase(retval.size() - mtx.size());
  649.         return retval;
  650.     }
  651.     // Try using local "data" directory
  652.     full_path = "data";
  653.     full_path += CFile::AddTrailingPathSeparator(full_path);
  654.     full_path += mtx;
  655.     if (CFile(full_path).Exists()) {
  656.         retval = full_path;
  657.         retval.erase(retval.size() - mtx.size());
  658.         return retval;
  659.     }
  660.     CNcbiApplication* app = CNcbiApplication::Instance();
  661.     if (!app)
  662.         return retval;
  663.     const string& blastmat_env = app->GetEnvironment().Get("BLASTMAT");
  664.     if (CFile(blastmat_env).Exists()) {
  665.         full_path = blastmat_env;
  666.         full_path += CFile::AddTrailingPathSeparator(full_path);
  667.         full_path += is_prot ? "aa" : "nt";
  668.         full_path += CFile::AddTrailingPathSeparator(full_path);
  669.         full_path += mtx;
  670.         if (CFile(full_path).Exists()) {
  671.             retval = full_path;
  672.             retval.erase(retval.size() - mtx.size());
  673.             return retval;
  674.         }
  675.     }
  676. #ifdef OS_UNIX
  677.     full_path = BLASTMAT_DIR;
  678.     full_path += CFile::AddTrailingPathSeparator(full_path);
  679.     full_path += is_prot ? "aa" : "nt";
  680.     full_path += CFile::AddTrailingPathSeparator(full_path);
  681.     full_path += mtx;
  682.     if (CFile(full_path).Exists()) {
  683.         retval = full_path;
  684.         retval.erase(retval.size() - mtx.size());
  685.         return retval;
  686.     }
  687. #endif
  688.     // Try again without the "aa" or "nt"
  689.     if (CFile(blastmat_env).Exists()) {
  690.         full_path = blastmat_env;
  691.         full_path += CFile::AddTrailingPathSeparator(full_path);
  692.         full_path += mtx;
  693.         if (CFile(full_path).Exists()) {
  694.             retval = full_path;
  695.             retval.erase(retval.size() - mtx.size());
  696.             return retval;
  697.         }
  698.     }
  699. #ifdef OS_UNIX
  700.     full_path = BLASTMAT_DIR;
  701.     full_path += CFile::AddTrailingPathSeparator(full_path);
  702.     full_path += mtx;
  703.     if (CFile(full_path).Exists()) {
  704.         retval = full_path;
  705.         retval.erase(retval.size() - mtx.size());
  706.         return retval;
  707.     }
  708. #endif
  709.     return retval;
  710. }
  711. /// Checks if a BLAST database exists at a given file path: looks for 
  712. /// an alias file first, then for an index file
  713. static bool BlastDbFileExists(string& path, bool is_prot)
  714. {
  715.     // Check for alias file first
  716.     string full_path = path + (is_prot ? ".pal" : ".nal");
  717.     if (CFile(full_path).Exists())
  718.         return true;
  719.     // Check for an index file
  720.     full_path = path + (is_prot ? ".pin" : ".nin");
  721.     if (CFile(full_path).Exists())
  722.         return true;
  723.     return false;
  724. }
  725. string
  726. FindBlastDbPath(const char* dbname, bool is_prot)
  727. {
  728.     string retval;
  729.     string full_path;       // full path to matrix file
  730.     if (!dbname)
  731.         return retval;
  732.     string database(dbname);
  733.     // Look for matrix file in local directory
  734.     full_path = database;
  735.     if (BlastDbFileExists(full_path, is_prot)) {
  736.         return retval;
  737.     }
  738.     CNcbiApplication* app = CNcbiApplication::Instance();
  739.     if (app) {
  740.         const string& blastdb_env = app->GetEnvironment().Get("BLASTDB");
  741.         if (CFile(blastdb_env).Exists()) {
  742.             full_path = blastdb_env;
  743.             full_path += CFile::AddTrailingPathSeparator(full_path);
  744.             full_path += database;
  745.             if (BlastDbFileExists(full_path, is_prot)) {
  746.                 retval = full_path;
  747.                 retval.erase(retval.size() - database.size());
  748.                 return retval;
  749.             }
  750.         }
  751.     }
  752.     // Obtain the matrix path from the ncbi configuration file
  753.     CMetaRegistry::SEntry sentry;
  754.     sentry = CMetaRegistry::Load("ncbi", CMetaRegistry::eName_RcOrIni);
  755.     string path = 
  756.         sentry.registry ? sentry.registry->Get("BLAST", "BLASTDB") : "";
  757.     full_path = CFile::MakePath(path, database);
  758.     if (BlastDbFileExists(full_path, is_prot)) {
  759.         retval = full_path;
  760.         retval.erase(retval.size() - database.size());
  761.         return retval;
  762.     }
  763.     return retval;
  764. }
  765. unsigned int
  766. GetNumberOfFrames(EProgram p)
  767. {
  768.     unsigned int retval = 0;
  769.     switch (p) {
  770.     case eBlastn:
  771.         retval = 2;
  772.         break;
  773.     case eBlastp:
  774.     case eRPSBlast:
  775.     case eTblastn: 
  776.     case eRPSTblastn: 
  777.         retval = 1;
  778.         break;
  779.     case eBlastx:
  780.     case eTblastx:
  781.         retval = 6;
  782.         break;
  783.     default:
  784.         NCBI_THROW(CBlastException, eBadParameter, 
  785.                    "Cannot get number of frames for invalid program type");
  786.     }
  787.     return retval;
  788. }
  789. END_SCOPE(blast)
  790. END_NCBI_SCOPE
  791. /* @} */
  792. /*
  793. * ===========================================================================
  794. *
  795. * $Log: blast_setup_cxx.cpp,v $
  796. * Revision 1000.7  2004/06/01 18:05:58  gouriano
  797. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.68
  798. *
  799. * Revision 1.68  2004/05/21 21:41:02  gorelenk
  800. * Added PCH ncbi_pch.hpp
  801. *
  802. * Revision 1.67  2004/04/19 19:52:02  papadopo
  803. * correct off-by-one error in sequence size computation
  804. *
  805. * Revision 1.66  2004/04/16 14:28:49  papadopo
  806. * add use of eRPSBlast and eRPSTblastn programs
  807. *
  808. * Revision 1.65  2004/04/07 03:06:15  camacho
  809. * Added blast_encoding.[hc], refactoring blast_stat.[hc]
  810. *
  811. * Revision 1.64  2004/04/06 20:45:28  dondosha
  812. * Added function FindBlastDbPath: should be moved to seqdb library
  813. *
  814. * Revision 1.63  2004/03/24 19:14:48  dondosha
  815. * Fixed memory leaks
  816. *
  817. * Revision 1.62  2004/03/19 19:22:55  camacho
  818. * Move to doxygen group AlgoBlast, add missing CVS logs at EOF
  819. *
  820. * Revision 1.61  2004/03/15 19:57:52  dondosha
  821. * SetupSubjects takes just program argument instead of CBlastOptions*
  822. *
  823. * Revision 1.60  2004/03/11 17:26:46  dicuccio
  824. * Use NStr::ToUpper() instead of transform
  825. *
  826. * Revision 1.59  2004/03/09 18:53:25  dondosha
  827. * Do not set db length and number of sequences options to real values - these are calculated and assigned to parameters structure fields
  828. *
  829. * Revision 1.58  2004/03/06 00:39:47  camacho
  830. * Some refactorings, changed boolen parameter to enum in GetSequence
  831. *
  832. * Revision 1.57  2004/02/24 18:14:56  dondosha
  833. * Set the maximal length in the set of queries, when filling BlastQueryInfo structure
  834. *
  835. * Revision 1.56  2004/02/18 15:16:28  camacho
  836. * Consolidated ncbi2na mask definition
  837. *
  838. * Revision 1.55  2004/01/07 17:39:27  vasilche
  839. * Fixed include path to genbank loader.
  840. *
  841. * Revision 1.54  2003/12/29 17:00:57  camacho
  842. * Update comment
  843. *
  844. * Revision 1.53  2003/12/15 19:55:14  camacho
  845. * Minor fix to ensure exception safety
  846. *
  847. * Revision 1.52  2003/12/03 16:43:47  dondosha
  848. * Renamed BlastMask to BlastMaskLoc, BlastResults to BlastHSPResults
  849. *
  850. * Revision 1.51  2003/11/26 18:36:45  camacho
  851. * Renaming blast_option*pp -> blast_options*pp
  852. *
  853. * Revision 1.50  2003/11/26 18:24:00  camacho
  854. * +Blast Option Handle classes
  855. *
  856. * Revision 1.49  2003/11/24 17:12:44  dondosha
  857. * Query info structure does not have a total_length member any more; use last context offset
  858. *
  859. * Revision 1.48  2003/11/06 21:25:37  camacho
  860. * Revert previous change, add assertions
  861. *
  862. * Revision 1.47  2003/11/04 17:14:22  dondosha
  863. * Length in subject sequence block C structure should not include sentinels
  864. *
  865. * Revision 1.46  2003/10/31 19:45:03  camacho
  866. * Fix setting of subject sequence length
  867. *
  868. * Revision 1.45  2003/10/31 16:53:32  dondosha
  869. * Set length in query sequence block correctly
  870. *
  871. * Revision 1.44  2003/10/29 04:46:16  camacho
  872. * Use fixed AutoPtr for GetSequence return value
  873. *
  874. * Revision 1.43  2003/10/27 21:27:36  camacho
  875. * Remove extra argument to GetSequenceView, minor refactorings
  876. *
  877. * Revision 1.42  2003/10/22 14:21:55  camacho
  878. * Added sanity checking assertions
  879. *
  880. * Revision 1.41  2003/10/21 13:04:54  camacho
  881. * Fix bug in SetupSubjects, use sequence blk set functions
  882. *
  883. * Revision 1.40  2003/10/16 13:38:54  coulouri
  884. * use anonymous exceptions to fix unreferenced variable compiler warning
  885. *
  886. * Revision 1.39  2003/10/15 18:18:00  camacho
  887. * Fix to setup query info structure for proteins
  888. *
  889. * Revision 1.38  2003/10/15 15:09:32  camacho
  890. * Changes from Mike DiCuccio to use GetSequenceView to retrieve sequences.
  891. *
  892. * Revision 1.37  2003/10/08 15:13:56  dondosha
  893. * Test if subject mask is not NULL before converting to a C structure
  894. *
  895. * Revision 1.36  2003/10/08 15:05:47  dondosha
  896. * Test if mask is not NULL before converting to a C structure
  897. *
  898. * Revision 1.35  2003/10/07 17:34:05  dondosha
  899. * Add lower case masks to SSeqLocs forming the vector of sequence locations
  900. *
  901. * Revision 1.34  2003/10/03 16:12:18  dondosha
  902. * Fix in previous change for plus strand search
  903. *
  904. * Revision 1.33  2003/10/02 22:10:46  dondosha
  905. * Corrections for one-strand translated searches
  906. *
  907. * Revision 1.32  2003/09/30 03:23:18  camacho
  908. * Fixes to FindMatrixPath
  909. *
  910. * Revision 1.31  2003/09/29 21:38:29  camacho
  911. * Assign retval only when successfully found path to matrix
  912. *
  913. * Revision 1.30  2003/09/29 20:35:03  camacho
  914. * Replace abort() with exception in GetNumberOfFrames
  915. *
  916. * Revision 1.29  2003/09/16 16:48:13  dondosha
  917. * Use BLAST_PackDNA and BlastSetUp_SeqBlkNew from the core blast library for setting up subject sequences
  918. *
  919. * Revision 1.28  2003/09/12 17:52:42  camacho
  920. * Stop using pair<> as return value from GetSequence
  921. *
  922. * Revision 1.27  2003/09/11 20:55:01  camacho
  923. * Temporary fix for AutoPtr return value
  924. *
  925. * Revision 1.26  2003/09/11 17:45:03  camacho
  926. * Changed CBlastOption -> CBlastOptions
  927. *
  928. * Revision 1.25  2003/09/10 04:27:43  camacho
  929. * 1) Minor change to return type of GetSequence
  930. * 2) Fix to previous revision
  931. *
  932. * Revision 1.24  2003/09/09 22:15:02  dondosha
  933. * Added cast in return statement in GetSequence method, fixing compiler error
  934. *
  935. * Revision 1.23  2003/09/09 15:57:23  camacho
  936. * Fix indentation
  937. *
  938. * Revision 1.22  2003/09/09 14:21:39  coulouri
  939. * change blastkar.h to blast_stat.h
  940. *
  941. * Revision 1.21  2003/09/09 12:57:15  camacho
  942. * + internal setup functions, use smart pointers to handle memory mgmt
  943. *
  944. * Revision 1.20  2003/09/05 19:06:31  camacho
  945. * Use regular new to allocate genetic code string
  946. *
  947. * Revision 1.19  2003/09/03 19:36:27  camacho
  948. * Fix include path for blast_setup.hpp
  949. *
  950. * Revision 1.18  2003/08/28 22:42:54  camacho
  951. * Change BLASTGetSequence signature
  952. *
  953. * Revision 1.17  2003/08/28 15:49:02  madden
  954. * Fix for packing DNA as well as correct buflen
  955. *
  956. * Revision 1.16  2003/08/25 16:24:14  camacho
  957. * Updated BLASTGetMatrixPath
  958. *
  959. * Revision 1.15  2003/08/19 17:39:07  camacho
  960. * Minor fix to use of metaregistry class
  961. *
  962. * Revision 1.14  2003/08/18 20:58:57  camacho
  963. * Added blast namespace, removed *__.hpp includes
  964. *
  965. * Revision 1.13  2003/08/14 13:51:24  camacho
  966. * Use CMetaRegistry class to load the ncbi config file
  967. *
  968. * Revision 1.12  2003/08/11 15:17:39  dondosha
  969. * Added algo/blast/core to all #included headers
  970. *
  971. * Revision 1.11  2003/08/11 14:00:41  dicuccio
  972. * Indenting changes.  Fixed use of C++ namespaces (USING_SCOPE(objects) inside of
  973. * BEGIN_NCBI_SCOPE block)
  974. *
  975. * Revision 1.10  2003/08/08 19:43:07  dicuccio
  976. * Compilation fixes: #include file rearrangement; fixed use of 'list' and
  977. * 'vector' as variable names; fixed missing ostrea<< for __int64
  978. *
  979. * Revision 1.9  2003/08/04 15:18:23  camacho
  980. * Minor fixes
  981. *
  982. * Revision 1.8  2003/08/01 22:35:02  camacho
  983. * Added function to get matrix path (fixme)
  984. *
  985. * Revision 1.7  2003/08/01 17:40:56  dondosha
  986. * Use renamed functions and structures from local blastkar.h
  987. *
  988. * Revision 1.6  2003/07/31 19:45:33  camacho
  989. * Eliminate Ptr notation
  990. *
  991. * Revision 1.5  2003/07/30 15:00:01  camacho
  992. * Do not use Malloc/MemNew/MemFree
  993. *
  994. * Revision 1.4  2003/07/25 13:55:58  camacho
  995. * Removed unnecessary #includes
  996. *
  997. * Revision 1.3  2003/07/24 18:22:50  camacho
  998. * #include blastkar.h
  999. *
  1000. * Revision 1.2  2003/07/23 21:29:06  camacho
  1001. * Update BLASTFindGeneticCode to get genetic code string with C++ toolkit
  1002. *
  1003. * Revision 1.1  2003/07/10 18:34:19  camacho
  1004. * Initial revision
  1005. *
  1006. *
  1007. * ===========================================================================
  1008. */