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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: seqdb_src.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 18:06:22  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: seqdb_src.cpp,v 1000.1 2004/06/01 18:06:22 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:  Ilya Dondoshansky
  35. *
  36. */
  37. /// @file seqdb_src.cpp
  38. /// Implementation of the BlastSeqSrc interface for a C++ BLAST databases API
  39. #include <ncbi_pch.hpp>
  40. #include <objects/seqloc/Seq_id.hpp>
  41. #include <objmgr/util/sequence.hpp>
  42. #include <algo/blast/api/seqdb_src.hpp>
  43. #include <algo/blast/core/blast_util.h>
  44. #include <objtools/readers/seqdb/seqdb.hpp>
  45. #include "blast_setup.hpp"
  46. /** @addtogroup AlgoBlast
  47.  *
  48.  * @{
  49.  */
  50. USING_NCBI_SCOPE;
  51. USING_SCOPE(objects);
  52. USING_SCOPE(blast);
  53. extern "C" {
  54. /* Function prototypes */
  55. static Int4 SeqDbGetMaxLength(void* seqdb_handle, void* ignoreme);
  56. static Int4 SeqDbGetNumSeqs(void* seqdb_handle, void* ignoreme);
  57. static Int8 SeqDbGetTotLen(void* seqdb_handle, void* ignoreme);
  58. static Int4 SeqDbGetAvgLength(void* seqdb_handle, void* ignoreme);
  59. static char* SeqDbGetName(void* seqdb_handle, void* ignoreme);
  60. static char* SeqDbGetDefinition(void* seqdb_handle, void* ignoreme);
  61. static char* SeqDbGetDate(void* seqdb_handle, void* ignoreme);
  62. static Boolean SeqDbGetIsProt(void* seqdb_handle, void* ignoreme);
  63. static ListNode* SeqDbGetSeqLoc(void* seqdb_handle, void* args);
  64. static ListNode* SeqDbGetError(void* seqdb_handle, void* args);
  65. /** Retrieves the length of the longest sequence in the BlastSeqSrc.
  66.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  67.  * @param ignoreme Unused by this implementation [in]
  68.  */
  69. static Int4 SeqDbGetMaxLength(void* seqdb_handle, void*)
  70. {
  71.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  72.     return seqdb->GetMaxLength();
  73. }
  74. /** Retrieves the number of sequences in the BlastSeqSrc.
  75.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  76.  * @param ignoreme Unused by this implementation [in]
  77.  */
  78. static Int4 SeqDbGetNumSeqs(void* seqdb_handle, void*)
  79. {
  80.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  81.     return seqdb->GetNumSeqs();
  82. }
  83. /** Retrieves the total length of all sequences in the BlastSeqSrc.
  84.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  85.  * @param ignoreme Unused by this implementation [in]
  86.  */
  87. static Int8 SeqDbGetTotLen(void* seqdb_handle, void*)
  88. {
  89.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  90.     return seqdb->GetTotalLength();
  91. }
  92. /** Retrieves the average length of sequences in the BlastSeqSrc.
  93.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  94.  * @param ignoreme Unused by this implementation [in]
  95.  */
  96. static Int4 SeqDbGetAvgLength(void* seqdb_handle, void* ignoreme)
  97. {
  98.    Int8 total_length = SeqDbGetTotLen(seqdb_handle, ignoreme);
  99.    Int4 num_seqs = MAX(1, SeqDbGetNumSeqs(seqdb_handle, ignoreme));
  100.    return (Int4) (total_length/num_seqs);
  101. }
  102. /** Retrieves the name of the BLAST database.
  103.  * FIXME: RIGHT NOW THERE IS NO GETTER in CSeqDB for database name
  104.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  105.  * @param ignoreme Unused by this implementation [in]
  106.  */
  107. static char* SeqDbGetName(void* /*seqdb_handle*/, void*)
  108. {
  109. #if 0 // FIXME: GetName method not implemented in CSeqDb!!!
  110.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  111.     return strdup(seqdb->GetName().c_str());
  112. #else
  113.     return NULL;
  114. #endif
  115. }
  116. /** Retrieves the definition (title) of the BLAST database.
  117.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  118.  * @param ignoreme Unused by this implementation [in]
  119.  */
  120. static char* SeqDbGetDefinition(void* seqdb_handle, void*)
  121. {
  122.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  123.     return strdup(seqdb->GetTitle().c_str());
  124. }
  125. /** Retrieves the date of the BLAST database.
  126.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  127.  * @param ignoreme Unused by this implementation [in]
  128.  */
  129. static char* SeqDbGetDate(void* seqdb_handle, void*)
  130. {
  131.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  132.     return strdup(seqdb->GetDate().c_str());
  133. }
  134. /** Retrieves the date of the BLAST database.
  135.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  136.  * @param ignoreme Unused by this implementation [in]
  137.  */
  138. static Boolean SeqDbGetIsProt(void* seqdb_handle, void*)
  139. {
  140.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  141.     return (seqdb->GetSeqType() == 'p');
  142. }
  143. /** Retrieves the sequence meeting the criteria defined by its second argument.
  144.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  145.  * @param args Pointer to GetSeqArg structure [in]
  146.  * @return return codes defined in blast_seqsrc.h
  147.  */
  148. static Int2 SeqDbGetSequence(void* seqdb_handle, void* args)
  149. {
  150.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  151.     GetSeqArg* seqdb_args = (GetSeqArg*) args;
  152.     Int4 oid = -1, len = 0;
  153.     Boolean has_sentinel_byte;
  154.     Boolean buffer_allocated;
  155.     if (!seqdb || !seqdb_args)
  156.         return BLAST_SEQSRC_ERROR;
  157.     oid = seqdb_args->oid;
  158.     Uint1 encoding = seqdb_args->encoding;
  159.     has_sentinel_byte = (encoding == BLASTNA_ENCODING);
  160.     buffer_allocated = 
  161.        (encoding == BLASTNA_ENCODING || encoding == NCBI4NA_ENCODING);
  162.     /* free buffers if necessary */
  163.     if (seqdb_args->seq)
  164.         BlastSequenceBlkClean(seqdb_args->seq);
  165.     const char *buf;
  166.     if (!buffer_allocated) {
  167.         len = seqdb->GetSequence(oid, &buf);
  168.     } else {
  169.         len = seqdb->GetAmbigSeq(oid, &buf, has_sentinel_byte);
  170.     }
  171.     if (len <= 0)
  172.         return BLAST_SEQSRC_ERROR;
  173.     BlastSetUp_SeqBlkNew((Uint1*)buf, len, 0, &seqdb_args->seq, 
  174.                          buffer_allocated);
  175.     
  176.     /* If there is no sentinel byte, and buffer is allocated, i.e. this is
  177.        the traceback stage of a translated search, set "sequence" to the same 
  178.        position as "sequence_start". */
  179.     if (buffer_allocated && !has_sentinel_byte)
  180.        seqdb_args->seq->sequence = seqdb_args->seq->sequence_start;
  181.     seqdb_args->seq->oid = oid;
  182.     return BLAST_SEQSRC_SUCCESS;
  183. }
  184. /** Returns the memory allocated for the sequence buffer to the CSeqDB 
  185.  * interface.
  186.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  187.  * @param args Pointer to the GetSeqArgs structure, containing sequence block
  188.  *             with the buffer that needs to be deallocated. [in]
  189.  * @return return codes defined in blast_seqsrc.h
  190.  */
  191. static Int2 SeqDbRetSequence(void* seqdb_handle, void* args)
  192. {
  193.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  194.     GetSeqArg* seqdb_args = (GetSeqArg*) args;
  195.     if (!seqdb || !seqdb_args)
  196.         return BLAST_SEQSRC_ERROR;
  197.     if (seqdb_args->seq->sequence_start_allocated) {
  198.         seqdb->RetSequence((const char**)&seqdb_args->seq->sequence_start);
  199.         seqdb_args->seq->sequence_start_allocated = FALSE;
  200.         seqdb_args->seq->sequence_start = NULL;
  201.     }
  202.     return 0;
  203. }
  204. /** Retrieves the sequence identifier meeting the criteria defined by its 
  205.  * second argument. Currently it is an ordinal id (integer value).
  206.  * Client code is responsible for deallocating the return value. 
  207.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  208.  * @param args Pointer to integer indicating ordinal id [in]
  209.  * @return Sequence id structure generated from ASN.1 spec, 
  210.  *         cast to a void pointer.
  211.  */
  212. static ListNode* SeqDbGetSeqId(void* seqdb_handle, void* args)
  213. {
  214.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  215.     Uint4* oid = (Uint4*) args;
  216.     ListNode* seqid_wrap;
  217.     if (!seqdb || !oid)
  218.         return NULL;
  219.     list< CRef<CSeq_id> > seqid_list;
  220.     seqid_list = seqdb->GetSeqIDs(*oid);
  221.     CRef<CSeq_id>* seqid_ref = new CRef<CSeq_id>(seqid_list.front());
  222.     seqid_wrap = ListNodeAddPointer(NULL, BLAST_SEQSRC_CPP_SEQID_REF, 
  223.                                     (void*) seqid_ref);
  224.     return seqid_wrap;
  225. }
  226. /** Retrieves the sequence identifier meeting the criteria defined by its 
  227.  * second argument. Currently it is an ordinal id (integer value).
  228.  * @todo Need a way to request difference sequence identifiers in redundant
  229.  * databases.
  230.  * Client code is responsible for deallocating the return value. 
  231.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  232.  * @param args Pointer to integer indicating ordinal id [in]
  233.  */
  234. static char* SeqDbGetSeqIdStr(void* seqdb_handle, void* args)
  235. {
  236.     char* seqid_str = NULL;
  237.     ListNode* seqid_wrap = NULL;
  238.     seqid_wrap = SeqDbGetSeqId(seqdb_handle, args);
  239.     if (seqid_wrap->choice != BLAST_SEQSRC_CPP_SEQID_REF)
  240.         return NULL;
  241.     CRef<CSeq_id>* seqid_ref = (CRef<CSeq_id>*) seqid_wrap->ptr;
  242.     ListNodeFree(seqid_wrap);
  243.     if (seqid_ref)
  244.         seqid_str = strdup((*seqid_ref)->GetSeqIdString().c_str());
  245.     delete seqid_ref;
  246.     return seqid_str;
  247. }
  248. /* There is no need to return locations from seqdb, since we always search
  249.    whole sequences in the database */
  250. static ListNode* SeqDbGetSeqLoc(void*, void*)
  251. {
  252.    return NULL;
  253. }
  254. /** Retrieve length of a given database sequence.
  255.  * @param seqdb_handle Pointer to initialized CSeqDB object [in]
  256.  * @param args Pointer to integer indicating ordinal id [in]
  257.  * @return Length of the database sequence or BLAST_SEQSRC_ERROR.
  258.  */
  259. static Int4 SeqDbGetSeqLen(void* seqdb_handle, void* args)
  260. {
  261.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  262.     Int4* oid = (Int4*) args;
  263.     if (!seqdb || !oid)
  264.        return BLAST_SEQSRC_ERROR;
  265.     return seqdb->GetSeqLength(*oid);
  266. }
  267. /* There are no error messages saved in the SeqdbFILE structure, so the 
  268.  * following getter function is implemented as always returning NULL.
  269.  */
  270. static ListNode* SeqDbGetError(void*, void*)
  271. {
  272.     /* FIXME: error handling should not be provided by the seqsrc interface */
  273.    return NULL;
  274. }
  275. static Int2 SeqDbGetNextChunk(void* seqdb_handle, BlastSeqSrcIterator* itr)
  276. {
  277.     CSeqDB* seqdb = (CSeqDB*) seqdb_handle;
  278.     if (!seqdb || !itr)
  279.         return BLAST_SEQSRC_ERROR;
  280.     // Point current position to the next oid.
  281.     if (itr->next_oid == UINT4_MAX) {
  282.         return BLAST_SEQSRC_EOF;
  283.     } else if (itr->next_oid == 0) {
  284.         itr->current_pos = 0;
  285.         if (!seqdb->CheckOrFindOID(itr->current_pos))
  286.             return BLAST_SEQSRC_EOF;
  287.     } else {
  288.         itr->current_pos = itr->next_oid;
  289.     }
  290.     // Find the new next oid.
  291.     itr->next_oid = itr->current_pos + 1;
  292.     if (!seqdb->CheckOrFindOID(itr->next_oid))
  293.         itr->next_oid = UINT4_MAX;
  294.     itr->itr_type = eOidRange;
  295.     itr->oid_range[0] = itr->current_pos;
  296.     itr->oid_range[1] = itr->current_pos + 1;
  297.     return BLAST_SEQSRC_SUCCESS;
  298. }
  299. static Int4 SeqDbIteratorNext(void* seqsrc, BlastSeqSrcIterator* itr)
  300. {
  301.     BlastSeqSrc* bssp = (BlastSeqSrc*) seqsrc;
  302.     Int4 retval = BLAST_SEQSRC_EOF;
  303.     Int4 status = BLAST_SEQSRC_SUCCESS;
  304.     ASSERT(bssp);
  305.     ASSERT(itr);
  306.     /* If iterator is uninitialized/invalid, retrieve the next chunk from the
  307.      * BlastSeqSrc */
  308.     if (itr->current_pos == UINT4_MAX) {
  309.         status = BLASTSeqSrcGetNextChunk(bssp, itr);
  310.         if (status == BLAST_SEQSRC_ERROR || status == BLAST_SEQSRC_EOF) {
  311.             return status;
  312.         }
  313.     }
  314.     if (itr->itr_type == eOidRange) {
  315.         retval = itr->current_pos++;
  316.         if (itr->current_pos >= itr->oid_range[1]) {
  317.             itr->current_pos = UINT4_MAX;   /* invalidate iterator */
  318.         }
  319.     } else if (itr->itr_type == eOidList) {
  320.         /* Unimplemented iterator type! */
  321.         fprintf(stderr, "eOidList iterator type is not implementedn");
  322.         abort();
  323.     } else {
  324.         /* Unsupported/invalid iterator type! */
  325.         fprintf(stderr, "Invalid iterator type: %dn", itr->itr_type);
  326.         abort();
  327.     }
  328.     return retval;
  329. }
  330. }
  331. BEGIN_NCBI_SCOPE
  332. USING_SCOPE(objects);
  333. BEGIN_SCOPE(blast)
  334. extern "C" {
  335. BlastSeqSrc* SeqDbSrcNew(BlastSeqSrc* retval, void* args)
  336. {
  337.     SSeqDbSrcNewArgs* rargs = (SSeqDbSrcNewArgs*) args;
  338.     if (!retval)
  339.         return NULL;
  340.     ASSERT(rargs);
  341.     string db_name(rargs->dbname);
  342.     char db_type = static_cast<char>((rargs->is_protein ? 'p' : 'n'));
  343.     CSeqDB* seqdb(new CSeqDB(db_name, db_type, (Uint4)rargs->first_db_seq, 
  344.                              (Uint4)rargs->final_db_seq, true));
  345.     /* Initialize the BlastSeqSrc structure fields with user-defined function
  346.      * pointers and seqdb */
  347.     SetDeleteFnPtr(retval, &SeqDbSrcFree);
  348.     SetDataStructure(retval, (void*) seqdb);
  349.     SetGetNumSeqs(retval, &SeqDbGetNumSeqs);
  350.     SetGetMaxSeqLen(retval, &SeqDbGetMaxLength);
  351.     SetGetAvgSeqLen(retval, &SeqDbGetAvgLength);
  352.     SetGetTotLen(retval, &SeqDbGetTotLen);
  353.     SetGetAvgSeqLen(retval, &SeqDbGetAvgLength);
  354.     SetGetName(retval, &SeqDbGetName);
  355.     SetGetDefinition(retval, &SeqDbGetDefinition);
  356.     SetGetDate(retval, &SeqDbGetDate);
  357.     SetGetIsProt(retval, &SeqDbGetIsProt);
  358.     SetGetSequence(retval, &SeqDbGetSequence);
  359.     SetGetSeqIdStr(retval, &SeqDbGetSeqIdStr);
  360.     SetGetSeqId(retval, &SeqDbGetSeqId);
  361.     SetGetSeqLoc(retval, &SeqDbGetSeqLoc);
  362.     SetGetSeqLen(retval, &SeqDbGetSeqLen);
  363.     SetGetNextChunk(retval, &SeqDbGetNextChunk);
  364.     SetIterNext(retval, &SeqDbIteratorNext);
  365.     SetGetError(retval, &SeqDbGetError);
  366.     SetRetSequence(retval, &SeqDbRetSequence);
  367.     return retval;
  368. }
  369. BlastSeqSrc* SeqDbSrcFree(BlastSeqSrc* seq_src)
  370. {
  371.     if (!seq_src) 
  372.         return NULL;
  373.     CSeqDB* seqdb = static_cast<CSeqDB*>(GetDataStructure(seq_src));
  374.     delete seqdb;
  375.     sfree(seq_src);
  376.     return NULL;
  377. }
  378. }
  379. BlastSeqSrc* 
  380. SeqDbSrcInit(const char* dbname, Boolean is_prot, Int4 first_seq, 
  381.                       Int4 last_seq, void*)
  382. {
  383.     BlastSeqSrcNewInfo bssn_info;
  384.     BlastSeqSrc* seq_src = NULL;
  385.     SSeqDbSrcNewArgs* seqdb_args = 
  386.         (SSeqDbSrcNewArgs*) calloc(1, sizeof(SSeqDbSrcNewArgs));;
  387.     seqdb_args->dbname = strdup(dbname);
  388. seqdb_args->is_protein = is_prot ? true : false;
  389.     seqdb_args->first_db_seq = first_seq;
  390.     seqdb_args->final_db_seq = last_seq; 
  391.     bssn_info.constructor = &SeqDbSrcNew;
  392.     bssn_info.ctor_argument = (void*) seqdb_args;
  393.     seq_src = BlastSeqSrcNew(&bssn_info);
  394.     sfree(seqdb_args->dbname);
  395.     sfree(seqdb_args);
  396.     return seq_src;
  397. }
  398. END_SCOPE(blast)
  399. END_NCBI_SCOPE
  400. /* @} */
  401. /*
  402.  * ===========================================================================
  403.  *
  404.  * $Log: seqdb_src.cpp,v $
  405.  * Revision 1000.1  2004/06/01 18:06:22  gouriano
  406.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  407.  *
  408.  * Revision 1.11  2004/05/24 17:26:08  camacho
  409.  * Fix PC warning
  410.  *
  411.  * Revision 1.10  2004/05/21 21:41:02  gorelenk
  412.  * Added PCH ncbi_pch.hpp
  413.  *
  414.  * Revision 1.9  2004/05/19 15:26:47  dondosha
  415.  * Removed unused variables
  416.  *
  417.  * Revision 1.8  2004/05/17 18:11:15  dondosha
  418.  * Minor: eliminates strict compiler warning
  419.  *
  420.  * Revision 1.7  2004/05/17 15:49:07  dondosha
  421.  * Removed local variable declaration in empty SeqDbGetName method, to eliminate compiler warning
  422.  *
  423.  * Revision 1.6  2004/05/17 15:43:21  dondosha
  424.  * Return NULL from SeqDbGetName until CSeqDB gets a GetName method
  425.  *
  426.  * Revision 1.5  2004/04/28 19:38:20  dondosha
  427.  * Added implementation of BLASTSeqSrcRetSequence function
  428.  *
  429.  * Revision 1.4  2004/04/12 14:58:42  ucko
  430.  * Avoid placing static C functions inside namespace blocks to keep the
  431.  * SGI MIPSpro compiler from segfaulting in Scope Setup.
  432.  *
  433.  * Revision 1.3  2004/04/08 14:45:48  camacho
  434.  * 1. Added missing extern "C" declarations
  435.  * 2. Removed compiler warnings about unused parameters.
  436.  * 3. Removed dead code.
  437.  * 4. Added FIXMEs.
  438.  *
  439.  * Revision 1.2  2004/04/07 18:45:13  bealer
  440.  * - Update constructor for CSeqDB to omit obsolete first argument.
  441.  *
  442.  * Revision 1.1  2004/04/06 20:43:59  dondosha
  443.  * Sequence source for CSeqDB BLAST database interface
  444.  *
  445.  * ===========================================================================
  446.  */