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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: blast_engine.c,v $
  4.  * PRODUCTION Revision 1000.6  2004/06/01 18:07:09  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.135
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: blast_engine.c,v 1000.6 2004/06/01 18:07:09 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 offical 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 blast_engine.c
  38.  * High level BLAST functions
  39.  */
  40. static char const rcsid[] = 
  41.     "$Id: blast_engine.c,v 1000.6 2004/06/01 18:07:09 gouriano Exp $";
  42. #include <algo/blast/core/blast_engine.h>
  43. #include <algo/blast/core/lookup_wrap.h>
  44. #include <algo/blast/core/aa_ungapped.h>
  45. #include <algo/blast/core/blast_util.h>
  46. #include <algo/blast/core/blast_setup.h>
  47. #include <algo/blast/core/blast_gapalign.h>
  48. #include <algo/blast/core/blast_traceback.h>
  49. #include <algo/blast/core/phi_extend.h>
  50. #include <algo/blast/core/link_hsps.h>
  51. /** Deallocates all memory in BlastCoreAuxStruct */
  52. static BlastCoreAuxStruct* 
  53. BlastCoreAuxStructFree(BlastCoreAuxStruct* aux_struct)
  54. {
  55.    BlastExtendWordFree(aux_struct->ewp);
  56.    BLAST_InitHitListFree(aux_struct->init_hitlist);
  57.    Blast_HSPListFree(aux_struct->hsp_list);
  58.    sfree(aux_struct->query_offsets);
  59.    sfree(aux_struct->subject_offsets);
  60.    
  61.    sfree(aux_struct);
  62.    return NULL;
  63. }
  64. /** Adjust HSP coordinates for out-of-frame gapped extension.
  65.  * @param program One of blastx or tblastn [in]
  66.  * @param init_hitlist List of hits after ungapped extension [in]
  67.  * @param query_info Query information containing context offsets;
  68.  *                   needed for blastx only [in]
  69.  * @param subject_frame Frame of the subject sequence; tblastn only [in]
  70.  * @param subject_length Length of the original nucleotide subject sequence;
  71.  *                       tblastn only [in]
  72.  * @param offset Shift in the subject sequence protein coordinates [in]
  73.  */
  74. static void TranslateHSPsToDNAPCoord(Uint1 program, 
  75.         BlastInitHitList* init_hitlist, BlastQueryInfo* query_info,
  76.         Int2 subject_frame, Int4 subject_length, Int4 offset)
  77. {
  78.    BlastInitHSP* init_hsp;
  79.    Int4 index, context, frame;
  80.    Int4* context_offsets = query_info->context_offsets;
  81.    
  82.    for (index = 0; index < init_hitlist->total; ++index) {
  83.       init_hsp = &init_hitlist->init_hsp_array[index];
  84.       if (program == blast_type_blastx) {
  85.          context = 
  86.             BSearchInt4(init_hsp->q_off, context_offsets,
  87.                              query_info->last_context+1);
  88.          frame = context % 3;
  89.       
  90.          init_hsp->q_off = 
  91.             (init_hsp->q_off - context_offsets[context]) * CODON_LENGTH + 
  92.             context_offsets[context-frame] + frame;
  93.          init_hsp->ungapped_data->q_start = 
  94.             (init_hsp->ungapped_data->q_start - context_offsets[context]) 
  95.             * CODON_LENGTH + context_offsets[context-frame] + frame;
  96.       } else {
  97.          init_hsp->s_off += offset;
  98.          init_hsp->ungapped_data->s_start += offset;
  99.          if (subject_frame > 0) {
  100.             init_hsp->s_off = 
  101.                (init_hsp->s_off * CODON_LENGTH) + subject_frame - 1;
  102.             init_hsp->ungapped_data->s_start = 
  103.                (init_hsp->ungapped_data->s_start * CODON_LENGTH) + 
  104.                subject_frame - 1;
  105.          } else {
  106.             init_hsp->s_off = (init_hsp->s_off * CODON_LENGTH) + 
  107.                subject_length - subject_frame;
  108.             init_hsp->ungapped_data->s_start = 
  109.                (init_hsp->ungapped_data->s_start * CODON_LENGTH) + 
  110.                subject_length - subject_frame;
  111.          }
  112.       }
  113.    }
  114.    return;
  115. }
  116. /** The core of the BLAST search: comparison between the (concatenated)
  117.  * query against one subject sequence. Translation of the subject sequence
  118.  * into 6 frames is done inside, if necessary. If subject sequence is 
  119.  * too long, it can be split into several chunks. 
  120.  */
  121. static Int2
  122. BLAST_SearchEngineCore(Uint1 program_number, BLAST_SequenceBlk* query, 
  123.    BlastQueryInfo* query_info, BLAST_SequenceBlk* subject, 
  124.    LookupTableWrap* lookup, BlastGapAlignStruct* gap_align, 
  125.    BlastScoringParameters* score_params, 
  126.    BlastInitialWordParameters* word_params, 
  127.    BlastExtensionParameters* ext_params, 
  128.    BlastHitSavingParameters* hit_params, 
  129.    const BlastDatabaseOptions* db_options,
  130.    BlastDiagnostics* diagnostics,
  131.    BlastCoreAuxStruct* aux_struct,
  132.    BlastHSPList** hsp_list_out)
  133. {
  134.    BlastInitHitList* init_hitlist = aux_struct->init_hitlist;
  135.    BlastHSPList* hsp_list = aux_struct->hsp_list;
  136.    Uint1* translation_buffer = NULL;
  137.    Int4* frame_offsets = NULL;
  138.    BlastHitSavingOptions* hit_options = hit_params->options;
  139.    BlastScoringOptions* score_options = score_params->options;
  140.    BlastHSPList* combined_hsp_list = NULL;
  141.    Int2 status = 0;
  142.    Int4 context, first_context, last_context;
  143.    Int4 orig_length = subject->length;
  144.    Uint1* orig_sequence = subject->sequence;
  145.    Int4 **matrix;
  146.    Int4 hsp_num_max;
  147.    BlastUngappedStats* ungapped_stats = NULL;
  148.    BlastGappedStats* gapped_stats = NULL;
  149.    const Boolean k_translated_subject = (program_number == blast_type_tblastn
  150.                          || program_number == blast_type_tblastx
  151.                          || program_number == blast_type_rpstblastn);
  152.    if (k_translated_subject) {
  153.       first_context = 0;
  154.       last_context = 5;
  155.       if (score_options->is_ooframe) {
  156.          BLAST_GetAllTranslations(orig_sequence, NCBI2NA_ENCODING,
  157.             orig_length, db_options->gen_code_string, &translation_buffer,
  158.             &frame_offsets, &subject->oof_sequence);
  159.          subject->oof_sequence_allocated = TRUE;
  160.       } else {
  161.          BLAST_GetAllTranslations(orig_sequence, NCBI2NA_ENCODING,
  162.             orig_length, db_options->gen_code_string, &translation_buffer,
  163.             &frame_offsets, NULL);
  164.       }
  165.    } else if (program_number == blast_type_blastn) {
  166.       first_context = 1;
  167.       last_context = 1;
  168.    } else {
  169.       first_context = 0;
  170.       last_context = 0;
  171.    }
  172.    *hsp_list_out = NULL;
  173.    if (gap_align->positionBased)
  174.       matrix = gap_align->sbp->posMatrix;
  175.    else
  176.       matrix = gap_align->sbp->matrix;
  177.    hsp_num_max = (hit_options->hsp_num_max ? hit_options->hsp_num_max : INT4_MAX);
  178.    if (diagnostics) {
  179.       ungapped_stats = diagnostics->ungapped_stat;
  180.       gapped_stats = diagnostics->gapped_stat;
  181.    }
  182.    /* Loop over frames of the subject sequence */
  183.    for (context=first_context; context<=last_context; context++) {
  184.       Int4 chunk; /* loop variable below. */
  185.       Int4 num_chunks; /* loop variable below. */
  186.       Int4 offset = 0; /* Used as offset into subject sequence (if chunked) */
  187.       Int4 total_subject_length; /* Length of subject sequence used when split. */
  188.       if (k_translated_subject) {
  189.          subject->frame = BLAST_ContextToFrame(blast_type_blastx, context);
  190.          subject->sequence = 
  191.             translation_buffer + frame_offsets[context] + 1;
  192.          subject->length = 
  193.            frame_offsets[context+1] - frame_offsets[context] - 1;
  194.       } else {
  195.          subject->frame = context;
  196.       }
  197.      
  198.       /* Split subject sequence into chunks if it is too long */
  199.       num_chunks = (subject->length - DBSEQ_CHUNK_OVERLAP) / 
  200.          (MAX_DBSEQ_LEN - DBSEQ_CHUNK_OVERLAP) + 1;
  201.       total_subject_length = subject->length;
  202.       
  203.       for (chunk = 0; chunk < num_chunks; ++chunk) {
  204.          if (chunk > 0) {
  205.             offset += subject->length - DBSEQ_CHUNK_OVERLAP;
  206.             if (program_number == blast_type_blastn) {
  207.                subject->sequence += 
  208.                   (subject->length - DBSEQ_CHUNK_OVERLAP)/COMPRESSION_RATIO;
  209.             } else {
  210.                subject->sequence += (subject->length - DBSEQ_CHUNK_OVERLAP);
  211.             }
  212.          }
  213.          subject->length = MIN(total_subject_length - offset, 
  214.                                MAX_DBSEQ_LEN);
  215.          
  216.          BlastInitHitListReset(init_hitlist);
  217.          
  218.          aux_struct->WordFinder(subject, query, lookup, 
  219.             matrix, word_params, aux_struct->ewp, aux_struct->query_offsets, 
  220.             aux_struct->subject_offsets, GetOffsetArraySize(lookup), 
  221.             init_hitlist, ungapped_stats);
  222.             
  223.          if (init_hitlist->total == 0)
  224.             continue;
  225.          
  226.          if (score_options->gapped_calculation) {
  227.             Int4 prot_length = 0;
  228.             if (score_options->is_ooframe) {
  229.                /* Convert query offsets in all HSPs into the mixed-frame  
  230.                   coordinates */
  231.                TranslateHSPsToDNAPCoord(program_number, init_hitlist, 
  232.                   query_info, subject->frame, orig_length, offset);
  233.                if (k_translated_subject) {
  234.                   prot_length = subject->length;
  235.                   subject->length = 2*orig_length + 1;
  236.                }
  237.             }
  238.             /** NB: If queries are concatenated, HSP offsets must be adjusted
  239.              * inside the following function call, so coordinates are
  240.              * relative to the individual contexts (i.e. queries, strands or
  241.              * frames). Contexts should also be filled in HSPs when they 
  242.              * are saved.
  243.             */
  244.             aux_struct->GetGappedScore(program_number, query, query_info, 
  245.                subject, gap_align, score_params, ext_params, hit_params, 
  246.                init_hitlist, &hsp_list, gapped_stats);
  247.             if (score_options->is_ooframe && k_translated_subject)
  248.                subject->length = prot_length;
  249.          } else {
  250.             BLAST_GetUngappedHSPList(init_hitlist, query_info, subject,
  251.                                      hit_options, &hsp_list);
  252.          }
  253.          if (hsp_list->hspcnt == 0)
  254.             continue;
  255.          
  256.          /* The subject ordinal id is not yet filled in this HSP list */
  257.          hsp_list->oid = subject->oid;
  258.          
  259.          /* Assign frames in all HSPs. */
  260.          Blast_HSPListSetFrames(program_number, hsp_list, 
  261.                                 score_options->is_ooframe);
  262.          
  263.          Blast_HSPListAdjustOffsets(hsp_list, offset);
  264.          /* Allow merging of HSPs either if traceback is already 
  265.             available, or if it is an ungapped search */
  266.          Blast_HSPListsMerge(hsp_list, &combined_hsp_list, hsp_num_max, offset,
  267.             (Boolean) (hsp_list->traceback_done || !score_options->gapped_calculation));
  268.       } /* End loop on chunks of subject sequence */
  269.       
  270.       Blast_HSPListAppend(combined_hsp_list, hsp_list_out, hsp_num_max);
  271.       combined_hsp_list = Blast_HSPListFree(combined_hsp_list);
  272.    } /* End loop on frames */
  273.    /* Restore the original contents of the subject block */
  274.    subject->length = orig_length;
  275.    subject->sequence = orig_sequence;
  276.    hsp_list = *hsp_list_out;
  277.    if (hit_params->do_sum_stats == TRUE) {
  278.       status = BLAST_LinkHsps(program_number, hsp_list, query_info,
  279.                               subject, gap_align->sbp, hit_params, 
  280.                               score_options->gapped_calculation);
  281.    } else if (hit_options->phi_align) {
  282.       /* These e-values will not be accurate yet, since we don't know
  283.          the number of pattern occurrencies in the database. That
  284.          is arbitrarily set to 1 at this time. */
  285.       Blast_HSPListPHIGetEvalues(hsp_list, gap_align->sbp);
  286.    } else {
  287.       /* Calculate e-values for all HSPs. Skip this step
  288.          for RPS blast, since calculating the E values 
  289.          requires precomputation that has not been done yet */
  290.       if (program_number != blast_type_rpsblast &&
  291.           program_number != blast_type_rpstblastn)
  292.          status = Blast_HSPListGetEvalues(program_number, query_info, 
  293.                      hsp_list, score_options->gapped_calculation, 
  294.                      gap_align->sbp);
  295.    }
  296.    
  297.    /* Discard HSPs that don't pass the e-value test */
  298.    status = Blast_HSPListReapByEvalue(hsp_list, hit_options);
  299.    if (gapped_stats && hsp_list && hsp_list->hspcnt > 0) {
  300.       ++gapped_stats->num_seqs_passed;
  301.       gapped_stats->good_extensions += hsp_list->hspcnt;
  302.    }
  303.    if (translation_buffer) {
  304.        sfree(translation_buffer);
  305.    }
  306.    if (frame_offsets) {
  307.        sfree(frame_offsets);
  308.    }
  309.    return status;
  310. }
  311. static Int2 
  312. FillReturnCutoffsInfo(BlastRawCutoffs* return_cutoffs, 
  313.    BlastScoringParameters* score_params, 
  314.    BlastInitialWordParameters* word_params, 
  315.    BlastExtensionParameters* ext_params)
  316. {
  317.    /* since the cutoff score here will be used for display
  318.       putposes, strip out any internal scaling of the scores */
  319.    Int4 scale_factor = (Int4)score_params->scale_factor;
  320.    if (!return_cutoffs)
  321.       return -1;
  322.    return_cutoffs->x_drop_ungapped = word_params->x_dropoff / scale_factor;
  323.    return_cutoffs->x_drop_gap = ext_params->gap_x_dropoff / scale_factor;
  324.    return_cutoffs->x_drop_gap_final = ext_params->gap_x_dropoff_final / 
  325.                                                         scale_factor;
  326.    return_cutoffs->gap_trigger = ext_params->gap_trigger / scale_factor;
  327.    return 0;
  328. }
  329. /** Setup of the auxiliary BLAST structures; 
  330.  * also calculates internally used parameters from options. 
  331.  * @param program_number blastn, blastp, blastx, etc. [in]
  332.  * @param seq_src Sequence source information, with callbacks to get 
  333.  *             sequences, their lengths, etc. [in]
  334.  * @param scoring_options options for scoring. [in]
  335.  * @param eff_len_options  used to calculate effective lengths. [in]
  336.  * @param lookup_wrap Lookup table, already constructed. [in]
  337.  * @param word_options options for initial word finding. [in]
  338.  * @param ext_options options for gapped extension. [in]
  339.  * @param hit_options options for saving hits. [in]
  340.  * @param query The query sequence block [in]
  341.  * @param query_info The query information block [in]
  342.  * @param sbp Contains scoring information. [in]
  343.  * @param gap_align Gapped alignment information and allocated memory [out]
  344.  * @param score_params Parameters for scoring [out]
  345.  * @param word_params Parameters for initial word processing [out]
  346.  * @param ext_params Parameters for gapped extension [out]
  347.  * @param hit_params Parameters for saving hits [out]
  348.  * @param eff_len_params Parameters for calculating effective lengths [out]
  349.  * @param aux_struct_ptr Placeholder joining various auxiliary memory 
  350.  *                       structures [out]
  351.  */
  352. static Int2 
  353. BLAST_SetUpAuxStructures(Uint1 program_number,
  354.    const BlastSeqSrc* seq_src,
  355.    const BlastScoringOptions* scoring_options,
  356.    const BlastEffectiveLengthsOptions* eff_len_options,
  357.    LookupTableWrap* lookup_wrap,
  358.    const BlastInitialWordOptions* word_options,
  359.    const BlastExtensionOptions* ext_options,
  360.    const BlastHitSavingOptions* hit_options,
  361.    BLAST_SequenceBlk* query, BlastQueryInfo* query_info, 
  362.    BlastScoreBlk* sbp, 
  363.    BlastGapAlignStruct** gap_align, 
  364.    BlastScoringParameters** score_params,
  365.    BlastInitialWordParameters** word_params,
  366.    BlastExtensionParameters** ext_params,
  367.    BlastHitSavingParameters** hit_params,
  368.    BlastEffectiveLengthsParameters** eff_len_params,                         
  369.    BlastCoreAuxStruct** aux_struct_ptr)
  370. {
  371.    Int2 status = 0;
  372.    BlastCoreAuxStruct* aux_struct;
  373.    Boolean blastp = (lookup_wrap->lut_type == AA_LOOKUP_TABLE ||
  374.                          lookup_wrap->lut_type == RPS_LOOKUP_TABLE);
  375.    Boolean mb_lookup = (lookup_wrap->lut_type == MB_LOOKUP_TABLE);
  376.    Boolean phi_lookup = (lookup_wrap->lut_type == PHI_AA_LOOKUP ||
  377.                          lookup_wrap->lut_type == PHI_NA_LOOKUP);
  378.    Boolean ag_blast = (word_options->extension_method == eRightAndLeft);
  379.    Int4 offset_array_size = GetOffsetArraySize(lookup_wrap);
  380.    Uint4 avg_subj_length;
  381.    ASSERT(seq_src);
  382.    *aux_struct_ptr = aux_struct = (BlastCoreAuxStruct*)
  383.       calloc(1, sizeof(BlastCoreAuxStruct));
  384.    avg_subj_length = BLASTSeqSrcGetAvgSeqLen(seq_src);
  385.      
  386.    if ((status = BlastExtendWordNew(query->length, word_options, 
  387.                     avg_subj_length, &aux_struct->ewp)) != 0)
  388.       return status;
  389.    if ((status = BLAST_GapAlignSetUp(program_number, seq_src, 
  390.                     scoring_options, eff_len_options, ext_options, 
  391.                     hit_options, query_info, sbp, score_params,
  392.                     ext_params, hit_params, eff_len_params, gap_align)) != 0)
  393.       return status;
  394.       
  395.    BlastInitialWordParametersNew(program_number, word_options, 
  396.       *hit_params, *ext_params, sbp, query_info, 
  397.       avg_subj_length, word_params);
  398.    if (mb_lookup) {
  399.       aux_struct->WordFinder = MB_WordFinder;
  400.    } else if (phi_lookup) {
  401.       aux_struct->WordFinder = PHIBlastWordFinder;
  402.    } else if (blastp) {
  403.       aux_struct->WordFinder = BlastAaWordFinder;
  404.    } else if (ag_blast) {
  405.       aux_struct->WordFinder = BlastNaWordFinder_AG;
  406.    } else {
  407.       aux_struct->WordFinder = BlastNaWordFinder;
  408.    }
  409.    
  410.    aux_struct->query_offsets = 
  411.       (Uint4*) malloc(offset_array_size * sizeof(Uint4));
  412.    aux_struct->subject_offsets = 
  413.       (Uint4*) malloc(offset_array_size * sizeof(Uint4));
  414.    
  415.    aux_struct->init_hitlist = BLAST_InitHitListNew();
  416.    /* Pick which gapped alignment algorithm to use. */
  417.    if (phi_lookup)
  418.       aux_struct->GetGappedScore = PHIGetGappedScore;
  419.    else if (ext_options->ePrelimGapExt == eDynProgExt)
  420.       aux_struct->GetGappedScore = BLAST_GetGappedScore;
  421.    else
  422.       aux_struct->GetGappedScore = BLAST_MbGetGappedScore;
  423.    aux_struct->hsp_list = Blast_HSPListNew(hit_options->hsp_num_max);
  424.    return status;
  425. }
  426. #define BLAST_DB_CHUNK_SIZE 1024
  427. Int4 
  428. BLAST_RPSSearchEngine(Uint1 program_number, 
  429.    BLAST_SequenceBlk* query, BlastQueryInfo* query_info,
  430.    const BlastSeqSrc* seq_src,  BlastScoreBlk* sbp,
  431.    const BlastScoringOptions* score_options, 
  432.    LookupTableWrap* lookup_wrap,
  433.    const BlastInitialWordOptions* word_options, 
  434.    const BlastExtensionOptions* ext_options, 
  435.    const BlastHitSavingOptions* hit_options,
  436.    const BlastEffectiveLengthsOptions* eff_len_options,
  437.    const PSIBlastOptions* psi_options, 
  438.    const BlastDatabaseOptions* db_options,
  439.    BlastHSPResults* results, BlastDiagnostics* diagnostics)
  440. {
  441.    BlastCoreAuxStruct* aux_struct = NULL;
  442.    BlastHSPList* hsp_list;
  443.    BlastScoringParameters* score_params = NULL;
  444.    BlastInitialWordParameters* word_params = NULL;
  445.    BlastExtensionParameters* ext_params = NULL;
  446.    BlastHitSavingParameters* hit_params = NULL;
  447.    BlastEffectiveLengthsParameters* eff_len_params = NULL;
  448.    BlastGapAlignStruct* gap_align;
  449.    Int2 status = 0;
  450.    Int8 dbsize;
  451.    Int4 num_db_seqs;
  452.    Uint4 avg_subj_length = 0;
  453.    RPSLookupTable *lookup = (RPSLookupTable *)lookup_wrap->lut;
  454.    BlastQueryInfo concat_db_info;
  455.    BLAST_SequenceBlk concat_db;
  456.    RPSAuxInfo *rps_info;
  457.    BlastHSPResults prelim_results;
  458.    Uint1 *orig_query_seq = NULL;
  459.    BlastRawCutoffs* raw_cutoffs = NULL;
  460.    if (program_number != blast_type_rpsblast &&
  461.        program_number != blast_type_rpstblastn)
  462.       return -1;
  463.    if (results->num_queries != 1)
  464.       return -2;
  465.    if ((status =
  466.        BLAST_SetUpAuxStructures(program_number, seq_src,
  467.           score_options, eff_len_options, lookup_wrap, word_options,
  468.           ext_options, hit_options, query, query_info, sbp,
  469.           &gap_align, &score_params, &word_params, &ext_params,
  470.           &hit_params, &eff_len_params, &aux_struct)) != 0)
  471.       return status;
  472.    /* modify scoring and gap alignment structures for
  473.       use with RPS blast. */
  474.    rps_info = lookup->rps_aux_info;
  475.    gap_align->positionBased = TRUE;
  476.    gap_align->sbp->posMatrix = lookup->rps_pssm;
  477.    /* determine the total number of residues in the db.
  478.       This figure must also include one trailing NULL for
  479.       each DB sequence */
  480.    num_db_seqs = BLASTSeqSrcGetNumSeqs(seq_src);
  481.    dbsize = BLASTSeqSrcGetTotLen(seq_src) + num_db_seqs;
  482.    if (dbsize > INT4_MAX)
  483.       return -3;
  484.    /* If this is a translated search, pack the query into
  485.       ncbi2na format (exclude the starting sentinel); otherwise 
  486.       just use the input query */
  487.    if (program_number == blast_type_rpstblastn) {
  488.        orig_query_seq = query->sequence_start;
  489.        query->sequence_start++;
  490.        if (BLAST_PackDNA(query->sequence_start, query->length,
  491.                          NCBI4NA_ENCODING, &query->sequence) != 0)
  492.            return -4;
  493.    }
  494.    /* Concatenate all of the DB sequences together, and pretend
  495.       this is a large multiplexed sequence. Note that because the
  496.       scoring is position-specific, the actual sequence data is
  497.       not needed */
  498.    memset(&concat_db, 0, sizeof(concat_db)); /* fill in SequenceBlk */
  499.    concat_db.length = (Int4) dbsize;
  500.    memset(&concat_db_info, 0, sizeof(concat_db_info)); /* fill in QueryInfo */
  501.    concat_db_info.num_queries = num_db_seqs;
  502.    concat_db_info.first_context = 0;
  503.    concat_db_info.last_context = num_db_seqs - 1;
  504.    concat_db_info.context_offsets = lookup->rps_seq_offsets;
  505.    prelim_results.num_queries = num_db_seqs;
  506.    prelim_results.hitlist_array = (BlastHitList **)calloc(num_db_seqs,
  507.                                              sizeof(BlastHitList *));
  508.    /* Change the table of diagonals that will be used for the
  509.       search; we need a diag table that can fit the entire
  510.       concatenated DB */
  511.    avg_subj_length = (Uint4) (dbsize / num_db_seqs);
  512.    BlastExtendWordFree(aux_struct->ewp);
  513.    BlastExtendWordNew(concat_db.length, word_options, 
  514. avg_subj_length, &aux_struct->ewp);
  515.    /* Run the search; the input query is what gets scanned
  516.       and the concatenated DB is the sequence associated with
  517.       the score matrix. This essentially means that 'query'
  518.       and 'subject' have opposite conventions for the search. 
  519.     
  520.       Note that while scores can be calculated for any alignment
  521.       found, we have not set up any Karlin parameters or effective
  522.       search space sizes for the concatenated DB. This means that
  523.       E-values cannot be calculated after hits are found. */
  524.    BLAST_SearchEngineCore(program_number, &concat_db, &concat_db_info, 
  525.          query, lookup_wrap, gap_align, score_params, 
  526.          word_params, ext_params, hit_params, db_options, 
  527.          diagnostics, aux_struct, &hsp_list);
  528.    /* Fill the cutoff values in the diagnostics structure */
  529.    if (diagnostics->cutoffs)
  530.       raw_cutoffs = diagnostics->cutoffs;
  531.    FillReturnCutoffsInfo(raw_cutoffs, score_params, word_params, ext_params);
  532.    /* save the resulting list of HSPs. 'query' and 'subject' are
  533.       still reversed */
  534.    if (hsp_list && hsp_list->hspcnt > 0) {
  535.       /* Save the HSPs into a hit list */
  536.       Blast_HSPResultsSaveHitList(program_number, &prelim_results, hsp_list, hit_params);
  537.    }
  538.    /* Change the results from a single hsplist with many 
  539.       contexts to many hsplists each with a single context.
  540.       'query' and 'subject' offsets are still reversed. */
  541.    Blast_HSPResultsRPSUpdate(results, &prelim_results);
  542.    /* for a translated search, throw away the packed version
  543.       of the query and replace with the original (excluding the
  544.       starting sentinel) */
  545.    if (program_number == blast_type_rpstblastn) {
  546.        sfree(query->sequence);
  547.        query->sequence = query->sequence_start;
  548.    }
  549.    /* Do the traceback. After this call, query and 
  550.       subject have reverted to their traditional meanings. */
  551.    BLAST_RPSTraceback(program_number, results, &concat_db, 
  552.             &concat_db_info, query, query_info, gap_align, 
  553.             score_params, ext_params, hit_params, db_options, 
  554.             rps_info->karlin_k);
  555.    /* The traceback calculated the E values, so it's safe
  556.       to sort the results now */
  557.    Blast_HSPResultsSortByEvalue(results);
  558.    /* free the internal structures used */
  559.    /* Do not destruct score block here */
  560.    if (program_number == blast_type_rpstblastn) {
  561.       query->sequence_start = orig_query_seq;
  562.       query->sequence = orig_query_seq + 1;
  563.    }
  564.    sfree(prelim_results.hitlist_array);
  565.    gap_align->sbp->posMatrix = NULL;
  566.    gap_align->positionBased = FALSE;
  567.    gap_align->sbp = NULL;
  568.    BLAST_GapAlignStructFree(gap_align);
  569.    BlastCoreAuxStructFree(aux_struct);
  570.    sfree(score_params);
  571.    sfree(hit_params);
  572.    sfree(ext_params);
  573.    sfree(word_params);
  574.    sfree(eff_len_params);
  575.    return status;
  576. }
  577. Int4 
  578. BLAST_SearchEngine(Uint1 program_number, 
  579.    BLAST_SequenceBlk* query, BlastQueryInfo* query_info,
  580.    const BlastSeqSrc* seq_src,  BlastScoreBlk* sbp,
  581.    const BlastScoringOptions* score_options, 
  582.    LookupTableWrap* lookup_wrap,
  583.    const BlastInitialWordOptions* word_options, 
  584.    const BlastExtensionOptions* ext_options, 
  585.    const BlastHitSavingOptions* hit_options,
  586.    const BlastEffectiveLengthsOptions* eff_len_options,
  587.    const PSIBlastOptions* psi_options, 
  588.    const BlastDatabaseOptions* db_options,
  589.    BlastHSPResults* results, BlastDiagnostics* diagnostics)
  590. {
  591.    BlastCoreAuxStruct* aux_struct = NULL;
  592.    BlastHSPList* hsp_list; 
  593.    BlastScoringParameters* score_params = NULL;
  594.    BlastInitialWordParameters* word_params = NULL;
  595.    BlastExtensionParameters* ext_params = NULL;
  596.    BlastHitSavingParameters* hit_params = NULL;
  597.    BlastEffectiveLengthsParameters* eff_len_params = NULL;
  598.    BlastGapAlignStruct* gap_align;
  599.    GetSeqArg seq_arg;
  600.    Int2 status = 0;
  601.    BlastSeqSrcIterator* itr = NULL;
  602.    Int8 db_length = 0;
  603.    BlastRawCutoffs* raw_cutoffs = NULL;
  604.    
  605.    if ((status = 
  606.        BLAST_SetUpAuxStructures(program_number, seq_src,
  607.           score_options, eff_len_options, lookup_wrap, word_options, 
  608.           ext_options, hit_options, query, query_info, sbp, 
  609.           &gap_align, &score_params, &word_params, &ext_params, 
  610.           &hit_params, &eff_len_params, &aux_struct)) != 0)
  611.       return status;
  612.    memset((void*) &seq_arg, 0, sizeof(seq_arg));
  613.    /* Encoding is set so there are no sentinel bytes, and protein/nucleotide
  614.       sequences are retieved in ncbistdaa/ncbi2na encodings respectively. */
  615.    seq_arg.encoding = BLASTP_ENCODING; 
  616.    /* Initialize the iterator */
  617.    if ( !(itr = BlastSeqSrcIteratorNew(BLAST_DB_CHUNK_SIZE))) {
  618.       /** NEED AN ERROR MESSAGE HERE? */
  619.       return -1;
  620.    }
  621.    
  622.    db_length = BLASTSeqSrcGetTotLen(seq_src);
  623.    /* iterate over all subject sequences */
  624.    while ( (seq_arg.oid = BlastSeqSrcIteratorNext(seq_src, itr)) 
  625.            != BLAST_SEQSRC_EOF) {
  626.       BlastSequenceBlkClean(seq_arg.seq);
  627.       if (BLASTSeqSrcGetSequence(seq_src, (void*) &seq_arg) < 0)
  628.           continue;
  629.       if (db_length == 0) {
  630.          /* This is not a database search, hence need to recalculate and save
  631.             the effective search spaces and length adjustments for all 
  632.             queries based on the length of the current single subject 
  633.             sequence. */
  634.          if ((status = BLAST_OneSubjectUpdateParameters(program_number, 
  635.                           seq_arg.seq->length, score_options, query_info, 
  636.                           sbp, ext_params, hit_params, word_params, 
  637.                           eff_len_params)) != 0)
  638.             return status;
  639.       }
  640.       /* Calculate cutoff scores for linking HSPs */
  641.       if (hit_params->do_sum_stats) {
  642.          CalculateLinkHSPCutoffs(program_number, query_info, sbp, 
  643.                                  hit_params, ext_params, db_length, seq_arg.seq->length); 
  644.       }
  645.       BLAST_SearchEngineCore(program_number, query, query_info,
  646.          seq_arg.seq, lookup_wrap, gap_align, score_params, word_params, 
  647.          ext_params, hit_params, db_options, diagnostics, aux_struct, 
  648.          &hsp_list);
  649.  
  650.       if (hsp_list && hsp_list->hspcnt > 0) {
  651.          if (program_number == blast_type_blastn) {
  652.             status = 
  653.                Blast_HSPListReevaluateWithAmbiguities(hsp_list, query, 
  654.                   seq_arg.seq, hit_options, query_info, sbp, score_params, 
  655.                   seq_src);
  656.          }
  657.          /* Save the HSPs into a hit list */
  658.          Blast_HSPResultsSaveHitList(program_number, results, hsp_list, hit_params);
  659.       }
  660.          /*BlastSequenceBlkClean(subject);*/
  661.    }
  662.    
  663.    itr = BlastSeqSrcIteratorFree(itr);
  664.    BlastSequenceBlkFree(seq_arg.seq);
  665.    /* Fill the cutoff values in the diagnostics structure */
  666.    if (diagnostics->cutoffs)
  667.       raw_cutoffs = diagnostics->cutoffs;
  668.    FillReturnCutoffsInfo(raw_cutoffs, score_params, word_params, ext_params);
  669.    if (hit_options->phi_align) {
  670.       /* Save the product of effective occurrencies of pattern in query and
  671.          occurrencies of pattern in database */
  672.       Int8 db_hits = 1;
  673.       if (diagnostics && diagnostics->ungapped_stat)
  674.          db_hits = diagnostics->ungapped_stat->lookup_hits;
  675.       gap_align->sbp->effective_search_sp *= db_hits;
  676.    }
  677.    /* Now sort the hit lists for all queries, but only if this is a database
  678.       search. */
  679.    if (db_length > 0)
  680.       Blast_HSPResultsSortByEvalue(results);
  681.    if (!ext_options->skip_traceback && score_options->gapped_calculation) {
  682.       status = 
  683.          BLAST_ComputeTraceback(program_number, results, query, query_info,
  684.             seq_src, gap_align, score_params, ext_params, hit_params,
  685.             eff_len_params, db_options, psi_options);
  686.    }
  687.    /* Do not destruct score block here */
  688.    gap_align->sbp = NULL;
  689.    BLAST_GapAlignStructFree(gap_align);
  690.    BlastCoreAuxStructFree(aux_struct);
  691.    sfree(score_params);
  692.    sfree(hit_params);
  693.    sfree(ext_params);
  694.    sfree(word_params);
  695.    sfree(eff_len_params);
  696.    return status;
  697. }