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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: blast_lookup.c,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 18:07:25  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.25
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: blast_lookup.c,v 1000.3 2004/06/01 18:07:25 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. /** @file blast_lookup.c
  35.  * @todo FIXME needs file description
  36.  */
  37. #include <algo/blast/core/blast_def.h>
  38. #include <algo/blast/core/blast_options.h>
  39. #include <algo/blast/core/blast_lookup.h>
  40. #include <algo/blast/core/blast_rps.h>
  41. #include <algo/blast/core/lookup_util.h>
  42. #include <algo/blast/core/blast_encoding.h>
  43. #include "blast_inline.h"
  44. static char const rcsid[] = 
  45.     "$Id: blast_lookup.c,v 1000.3 2004/06/01 18:07:25 gouriano Exp $";
  46. static void AddWordHits( LookupTable *lookup,
  47.  Int4** matrix,
  48.  Uint1* word,
  49.  Int4 offset,
  50.                          Int4 query_bias);
  51. static void AddPSSMWordHits( LookupTable *lookup,
  52.  Int4** matrix,
  53.  Int4 offset,
  54.                          Int4 query_bias);
  55. Int4 BlastAaLookupNew(const LookupTableOptions* opt,
  56.       LookupTable* * lut)
  57. {
  58.   return LookupTableNew(opt, lut, TRUE);
  59. }
  60. Int4 RPSLookupTableNew(const RPSInfo *info,
  61.       RPSLookupTable* * lut)
  62. {
  63.    Int4 i;
  64.    RPSLookupFileHeader *lookup_header;
  65.    RPSProfileHeader *profile_header;
  66.    RPSLookupTable* lookup = *lut = 
  67.       (RPSLookupTable*) calloc(1, sizeof(RPSLookupTable));
  68.    Int4* pssm_start;
  69.    Int4 num_profiles;
  70.    Int4 num_pssm_rows;
  71.    Int4 longest_chain;
  72.    ASSERT(info != NULL);
  73.    /* Fill in the lookup table information. */
  74.    lookup_header = info->lookup_header;
  75.    if (lookup_header->magic_number != RPS_MAGIC_NUM)
  76.       return -1;
  77.    lookup->rps_aux_info = (RPSAuxInfo *)(&info->aux_info);
  78.    lookup->wordsize = BLAST_WORDSIZE_PROT;
  79.    lookup->alphabet_size = PSI_ALPHABET_SIZE;
  80.    lookup->charsize = ilog2(lookup->alphabet_size) + 1;
  81.    lookup->backbone_size = 1 << (lookup->wordsize * lookup->charsize);
  82.    lookup->mask = lookup->backbone_size - 1;
  83.    lookup->rps_backbone = (RPSBackboneCell *)((Uint1 *)lookup_header + 
  84.                           lookup_header->start_of_backbone);
  85.    lookup->overflow = (Int4 *)((Uint1 *)lookup_header + 
  86.     lookup_header->start_of_backbone + 
  87. (lookup->backbone_size + 1)* sizeof(RPSBackboneCell));
  88.    lookup->overflow_size = lookup_header->overflow_hits;
  89.    /* fill in the pv_array */
  90.    
  91.    lookup->pv = (PV_ARRAY_TYPE *)
  92.       calloc((lookup->backbone_size >> PV_ARRAY_BTS) , sizeof(PV_ARRAY_TYPE));
  93.    longest_chain = 0;
  94.    for (i = 0; i < lookup->backbone_size; i++) {
  95.       if (lookup->rps_backbone[i].num_used > 0) {
  96.  PV_SET(lookup,i);
  97.       }
  98.       if (lookup->rps_backbone[i].num_used > longest_chain) {
  99.          longest_chain = lookup->rps_backbone[i].num_used;
  100.       }
  101.    }
  102.    lookup->longest_chain = longest_chain;
  103.    /* Fill in the PSSM information */
  104.    profile_header = info->profile_header;
  105.    if (profile_header->magic_number != RPS_MAGIC_NUM)
  106.       return -2;
  107.    lookup->rps_seq_offsets = profile_header->start_offsets;
  108.    num_profiles = profile_header->num_profiles;
  109.    num_pssm_rows = lookup->rps_seq_offsets[num_profiles];
  110.    lookup->rps_pssm = (Int4 **)malloc((num_pssm_rows+1) * sizeof(Int4 *));
  111.    pssm_start = profile_header->start_offsets + num_profiles + 1;
  112.    for (i = 0; i < num_pssm_rows + 1; i++) {
  113.       lookup->rps_pssm[i] = pssm_start;
  114.       pssm_start += lookup->alphabet_size;
  115.    }
  116.    return 0;
  117. }
  118. Int4 LookupTableNew(const LookupTableOptions* opt,
  119.       LookupTable* * lut,
  120.       Boolean is_protein)
  121. {
  122.    LookupTable* lookup = *lut = 
  123.       (LookupTable*) calloc(1, sizeof(LookupTable));
  124.    ASSERT(lookup != NULL);
  125.   if (is_protein) {
  126.     Int4 i;
  127.     lookup->charsize = ilog2(opt->alphabet_size) + 1;
  128.     lookup->wordsize = opt->word_size;
  129.     lookup->backbone_size = 0;
  130.     for(i=0;i<lookup->wordsize;i++)
  131.         lookup->backbone_size |= (opt->alphabet_size - 1) << (i * lookup->charsize);
  132.     lookup->backbone_size += 1;
  133.     lookup->mask = makemask(opt->word_size * lookup->charsize);
  134.   } else {
  135.      lookup->word_length = opt->word_size;
  136.      lookup->scan_step = opt->scan_step;
  137.      lookup->charsize = ilog2(opt->alphabet_size / COMPRESSION_RATIO); 
  138.      lookup->wordsize = 
  139.         (opt->word_size - MIN(lookup->scan_step,COMPRESSION_RATIO) + 1) 
  140.         / COMPRESSION_RATIO;
  141.      lookup->reduced_wordsize = (lookup->wordsize >= 2) ? 2 : 1;
  142.      lookup->backbone_size = 
  143.        iexp(2,lookup->reduced_wordsize*lookup->charsize*COMPRESSION_RATIO);
  144.      lookup->mask = lookup->backbone_size - 1;
  145.   }
  146.   lookup->alphabet_size = opt->alphabet_size;
  147.   lookup->exact_matches=0;
  148.   lookup->neighbor_matches=0;
  149.   lookup->threshold = opt->threshold;
  150.   lookup->thin_backbone = 
  151.      (Int4**) calloc(lookup->backbone_size , sizeof(Int4*));
  152.   ASSERT(lookup->thin_backbone != NULL);
  153.   lookup->use_pssm = opt->use_pssm;
  154.   lookup->neighbors=NULL;
  155.   lookup->overflow=NULL;
  156.   return 0;
  157. }
  158. Int4 BlastAaLookupAddWordHit(LookupTable* lookup, /* in/out: the lookup table */
  159.                              Uint1* w,
  160.      Int4 query_offset)
  161. {
  162.   Int4 index=0;
  163.   Int4 chain_size = 0; /* total number of elements in the chain */
  164.   Int4 hits_in_chain = 0; /* number of occupied elements in the chain, not including the zeroth and first positions */ 
  165.   Int4 * chain = NULL;
  166.     
  167.   /* compute its index, */
  168.   _ComputeIndex(lookup->wordsize,lookup->charsize,lookup->mask, w, &index);
  169.   ASSERT(index < lookup->backbone_size);
  170.   /* if backbone cell is null, initialize a new chain */
  171.   if (lookup->thin_backbone[index] == NULL)
  172.     {
  173.       chain_size = 8;
  174.       hits_in_chain = 0;
  175.       chain = (Int4*) calloc( chain_size, sizeof(Int4) );
  176.       ASSERT(chain != NULL);
  177.       chain[0] = chain_size;
  178.       chain[1] = hits_in_chain;
  179.       lookup->thin_backbone[index] = chain;
  180.     }
  181.   else
  182.     /* otherwise, use the existing chain */
  183.     {
  184.       chain = lookup->thin_backbone[index];
  185.       chain_size = chain[0];
  186.       hits_in_chain = chain[1];
  187.     }
  188.   
  189.   /* if the chain is full, allocate more room */
  190.   if ( (hits_in_chain + 2) == chain_size )
  191.     {
  192.       chain_size = chain_size * 2;
  193.       chain = (Int4*) realloc(chain, chain_size * sizeof(Int4) );
  194.       ASSERT(chain != NULL);
  195.       lookup->thin_backbone[index] = chain;
  196.       chain[0] = chain_size;
  197.     }
  198.   
  199.   /* add the hit */
  200.   chain[ chain[1] + 2 ] = query_offset;
  201.   chain[1] += 1;
  202.   return 0;
  203. }
  204. Int4 _BlastAaLookupFinalize(LookupTable* lookup)
  205. {
  206.   Int4 i;
  207.   Int4 overflow_cells_needed=0;
  208.   Int4 overflow_cursor = 0;
  209.   Int4 backbone_occupancy=0;
  210.   Int4 thick_backbone_occupancy=0;
  211.   Int4 num_overflows=0;
  212.   Int4 longest_chain=0;
  213.   
  214. /* allocate the new lookup table */
  215.  lookup->thick_backbone = (LookupBackboneCell *)
  216.     calloc(lookup->backbone_size , sizeof(LookupBackboneCell));
  217.     ASSERT(lookup->thick_backbone != NULL);
  218.  /* allocate the pv_array */
  219.  lookup->pv = (PV_ARRAY_TYPE *)
  220.     calloc((lookup->backbone_size >> PV_ARRAY_BTS) + 1 , sizeof(PV_ARRAY_TYPE));
  221.   ASSERT(lookup->pv != NULL);
  222.  /* find out how many cells have >3 hits */
  223.  for(i=0;i<lookup->backbone_size;i++)
  224.    if (lookup->thin_backbone[i] != NULL)
  225.      {
  226.      if (lookup->thin_backbone[i][1] > HITS_ON_BACKBONE)
  227.        overflow_cells_needed += lookup->thin_backbone[i][1];
  228.      if (lookup->thin_backbone[i][1] > longest_chain)
  229.        longest_chain = lookup->thin_backbone[i][1];
  230.      }
  231.  lookup->longest_chain = longest_chain;
  232.  /* allocate the overflow array */
  233.  lookup->overflow = (Int4*) calloc( overflow_cells_needed, sizeof(Int4) );
  234.  ASSERT(lookup->overflow != NULL);
  235. /* for each position in the lookup table backbone, */
  236. for(i=0;i<lookup->backbone_size;i++)
  237.     {
  238.     /* if there are hits there, */
  239.     if ( lookup->thin_backbone[i] != NULL )
  240.         {
  241.         /* set the corresponding bit in the pv_array */
  242.   PV_SET(lookup,i);
  243.   backbone_occupancy++;
  244.         /* if there are three or fewer hits, */
  245.         if ( (lookup->thin_backbone[i])[1] <= HITS_ON_BACKBONE )
  246.             /* copy them into the thick_backbone cell */
  247.             {
  248.             Int4 j;
  249.     thick_backbone_occupancy++;
  250.     lookup->thick_backbone[i].num_used = lookup->thin_backbone[i][1];
  251.             for(j=0;j<lookup->thin_backbone[i][1];j++)
  252.                 lookup->thick_backbone[i].payload.entries[j] = lookup->thin_backbone[i][j+2];
  253.             }
  254.         else
  255.   /* more than three hits; copy to overflow array */
  256.             {
  257.       Int4 j;
  258.       num_overflows++;
  259.       lookup->thick_backbone[i].num_used = lookup->thin_backbone[i][1];
  260.       lookup->thick_backbone[i].payload.overflow_cursor = overflow_cursor;
  261.       for(j=0;j<lookup->thin_backbone[i][1];j++)
  262. {
  263.                 lookup->overflow[overflow_cursor] = lookup->thin_backbone[i][j+2];
  264. overflow_cursor++;
  265. }
  266.             }
  267.     /* done with this chain- free it */
  268.         sfree(lookup->thin_backbone[i]);
  269. lookup->thin_backbone[i]=NULL;
  270.         }
  271.     else
  272.         /* no hits here */
  273.         {
  274.         lookup->thick_backbone[i].num_used=0;
  275.         }
  276.     } /* end for */
  277.  lookup->overflow_size = overflow_cursor;
  278. /* done copying hit info- free the backbone */
  279.  sfree(lookup->thin_backbone);
  280.  lookup->thin_backbone=NULL;
  281. #ifdef LOOKUP_VERBOSE
  282.  printf("backbone size : %dnbackbone occupancy: %d (%f%%)nthick_backbone occupancy: %d (%f%%)nnum_overflows: %dnoverflow size: %dnlongest chain: %dn",lookup->backbone_size, backbone_occupancy, 100.0 * (float) backbone_occupancy/ (float) lookup->backbone_size, thick_backbone_occupancy, 100.0 * (float) thick_backbone_occupancy / (float) lookup->backbone_size, num_overflows, overflow_cells_needed,longest_chain);
  283.  printf("exact matches : %dnneighbor matches : %dn",lookup->exact_matches,lookup->neighbor_matches);
  284. #endif
  285.  return 0;
  286. }
  287. Int4 BlastAaScanSubject(const LookupTableWrap* lookup_wrap,
  288.                         const BLAST_SequenceBlk *subject,
  289.                         Int4* offset,
  290.                         Uint4 * NCBI_RESTRICT query_offsets,
  291.                         Uint4 * NCBI_RESTRICT subject_offsets,
  292.                         Int4 array_size
  293.    )
  294. {
  295.   Int4 index=0;
  296.   Uint1* s=NULL;
  297.   Uint1* s_first=NULL;
  298.   Uint1* s_last=NULL;
  299.   Int4 numhits = 0; /* number of hits found for a given subject offset */
  300.   Int4 totalhits = 0; /* cumulative number of hits found */
  301.   LookupTable* lookup = lookup_wrap->lut;
  302.   s_first = subject->sequence + *offset;
  303.   s_last  = subject->sequence + subject->length - lookup->wordsize; 
  304.   _ComputeIndex(lookup->wordsize - 1, /* prime the index */
  305. lookup->charsize,
  306. lookup->mask,
  307. s_first,
  308. &index);
  309.   for(s=s_first; s <= s_last; s++)
  310.     {
  311.       /* compute the index value */
  312.       _ComputeIndexIncremental(lookup->wordsize,lookup->charsize,lookup->mask, s, &index);
  313.       /* if there are hits... */
  314.       if (PV_TEST(lookup, index))
  315. {
  316.   numhits = lookup->thick_backbone[index].num_used;
  317.           ASSERT(numhits != 0);
  318.     
  319.   /* ...and there is enough space in the destination array, */
  320.   if ( numhits <= (array_size - totalhits) )
  321.     /* ...then copy the hits to the destination */
  322.     {
  323.       Int4* src;
  324.       Int4 i;
  325.       if ( numhits <= HITS_ON_BACKBONE )
  326. /* hits live in thick_backbone */
  327. src = lookup->thick_backbone[index].payload.entries;
  328.       else
  329. /* hits live in overflow array */
  330. src = & (lookup->overflow [ lookup->thick_backbone[index].payload.overflow_cursor ] );
  331.       
  332.       /* copy the hits. */
  333.       for(i=0;i<numhits;i++)
  334. {
  335.   query_offsets[i + totalhits] = src[i];
  336.   subject_offsets[i + totalhits] = s - subject->sequence;
  337. }
  338.       totalhits += numhits;
  339.     }
  340.   else
  341.     /* not enough space in the destination array; return early */
  342.     {
  343.       break;
  344.     }
  345. }
  346.       else
  347. /* no hits found */
  348. {
  349. }
  350.     }
  351.   /* if we get here, we fell off the end of the sequence */
  352.   *offset = s - subject->sequence;
  353.   return totalhits;
  354. }
  355. Int4 BlastRPSScanSubject(const LookupTableWrap* lookup_wrap,
  356.                         const BLAST_SequenceBlk *sequence,
  357.                         Int4* offset,
  358.                         Uint4 * table_offsets,
  359.                         Uint4 * sequence_offsets,
  360.                         Int4 array_size
  361.    )
  362. {
  363.   Int4 index=0;
  364.   Int4 table_correction;
  365.   Uint1* s=NULL;
  366.   Uint1* s_first=NULL;
  367.   Uint1* s_last=NULL;
  368.   Int4 numhits = 0; /* number of hits found for a given subject offset */
  369.   Int4 totalhits = 0; /* cumulative number of hits found */
  370.   RPSLookupTable* lookup = (RPSLookupTable *)lookup_wrap->lut;
  371.   RPSBackboneCell *cell;
  372.   s_first = sequence->sequence + *offset;
  373.   s_last  = sequence->sequence + sequence->length - lookup->wordsize; 
  374.   /* Calling code expects the returned sequence offsets to
  375.      refer to the *first letter* in a word. The legacy RPS blast
  376.      lookup table stores offsets to the *last* letter in each
  377.      word, and so a correction is needed */
  378.   table_correction = lookup->wordsize - 1;
  379.   _ComputeIndex(lookup->wordsize - 1, /* prime the index */
  380. lookup->charsize,
  381. lookup->mask,
  382. s_first,
  383. &index);
  384.   for(s=s_first; s <= s_last; s++)
  385.     {
  386.       /* compute the index value */
  387.       _ComputeIndexIncremental(lookup->wordsize,lookup->charsize,lookup->mask, s, &index);
  388.       /* if there are hits... */
  389.       if (PV_TEST(lookup, index))
  390. {
  391.   cell = &lookup->rps_backbone[index];
  392.   numhits = cell->num_used;
  393.           ASSERT(numhits != 0);
  394.     
  395.   if ( numhits <= (array_size - totalhits) )
  396.     {
  397.       Int4* src;
  398.       Int4 i;
  399.       if ( numhits <= RPS_HITS_PER_CELL ) {
  400. /* hits live in thick_backbone */
  401.         for(i=0;i<numhits;i++)
  402.   {
  403.     table_offsets[i + totalhits] = cell->entries[i] -
  404.                                                 table_correction;
  405.     sequence_offsets[i + totalhits] = s - sequence->sequence;
  406.   }
  407.               }
  408.       else {
  409. /* hits (past the first) live in overflow array */
  410. src = lookup->overflow + (cell->entries[1] / sizeof(Int4));
  411. table_offsets[totalhits] = cell->entries[0] - table_correction;
  412. sequence_offsets[totalhits] = s - sequence->sequence;
  413.         for(i=0;i<(numhits-1);i++)
  414.   {
  415.     table_offsets[i+totalhits+1] = src[i] - table_correction;
  416.     sequence_offsets[i+totalhits+1] = s - sequence->sequence;
  417.   }
  418.       }
  419.       totalhits += numhits;
  420.     }
  421.   else
  422.     /* not enough space in the destination array; return early */
  423.     {
  424.       break;
  425.     }
  426. }
  427.       else
  428. /* no hits found */
  429. {
  430. }
  431.     }
  432.   /* if we get here, we fell off the end of the sequence */
  433.   *offset = s - sequence->sequence;
  434.   return totalhits;
  435. }
  436. Int4 BlastAaLookupIndexQueries(LookupTable* lookup,
  437.        Int4 ** matrix,
  438.        BLAST_SequenceBlk* query,
  439.        ListNode* locations,
  440.        Int4 num_queries)
  441. {
  442.   Int4 i;
  443.   /* create neighbor array */
  444.   if (lookup->threshold>0)
  445.     {
  446.       MakeAllWordSequence(lookup);
  447.     }
  448.   /* index queries */
  449.   for(i=0;i<num_queries;i++)
  450.     {
  451.       _BlastAaLookupIndexQuery(lookup, matrix, 
  452.                                (lookup->use_pssm == TRUE) ? NULL : &(query[i]), 
  453.                                &(locations[i]), 0);
  454.     }
  455.   /* free neighbor array*/
  456.   if (lookup->neighbors != NULL)
  457.     sfree(lookup->neighbors);
  458.   return 0;
  459. }
  460. Int4 _BlastAaLookupIndexQuery(LookupTable* lookup,
  461.       Int4 ** matrix,
  462.       BLAST_SequenceBlk* query,
  463.       ListNode* location,
  464.                               Int4 query_bias)
  465. {
  466.   ListNode* loc;
  467.   Int4 from, to;
  468.   Int4 w;
  469.   for(loc=location; loc; loc=loc->next)
  470.     {
  471.       from = ((SSeqRange*) loc->ptr)->left;
  472.       to = ((SSeqRange*) loc->ptr)->right - lookup->wordsize + 1;
  473.       for(w=from;w<=to;w++)
  474. {
  475.   AddNeighboringWords(lookup,
  476.       matrix,
  477.       query,
  478.       w,
  479.                               query_bias);
  480. }      
  481.     }
  482.   return 0;
  483. }
  484. Int4 MakeAllWordSequence(LookupTable* lookup)
  485. {
  486.   Int4 k,n;
  487.   Int4 i;
  488.   Int4 len;
  489.   k=lookup->alphabet_size;
  490.   n=lookup->wordsize;
  491.   /* need k^n bytes for the de Bruijn sequence and n-1 to unwrap it. */ 
  492.   len = iexp(k,n) + (n-1);
  493.   
  494.   lookup->neighbors_length = len;
  495.   lookup->neighbors = (Uint1*) malloc( len );
  496.   ASSERT(lookup->neighbors != NULL);
  497.   /* generate the de Bruijn sequence */
  498.   debruijn(n,k,lookup->neighbors,NULL);
  499.   /* unwrap it */
  500.   for(i=0;i<(n-1);i++)
  501.     lookup->neighbors[len-n+1+i] = lookup->neighbors[i];
  502.   
  503.   return 0;
  504. }
  505. Int4 AddNeighboringWords(LookupTable* lookup, Int4 ** matrix, BLAST_SequenceBlk* query, Int4 offset, Int4 query_bias)
  506. {
  507.   
  508.   if (lookup->use_pssm)
  509.   {
  510.       AddPSSMWordHits(lookup, matrix, offset, query_bias);
  511.   }
  512.   else
  513.   {
  514.     Uint1* w = NULL;
  515.     ASSERT(query != NULL);
  516.     w = query->sequence + offset;
  517.   
  518.     if (lookup->threshold == 0)
  519.     {
  520.       BlastAaLookupAddWordHit(lookup, w, query_bias + offset);
  521.       lookup->exact_matches++;
  522.     }
  523.     else
  524.     {
  525.       AddWordHits(lookup, matrix, w, offset, query_bias);
  526.     }
  527.   }
  528.   return 0;
  529. }
  530. static void AddWordHits(LookupTable* lookup, Int4** matrix, 
  531. Uint1* word, Int4 offset, Int4 query_bias)
  532. {
  533.   Uint1* s = lookup->neighbors;
  534.   Uint1* s_end=s + lookup->neighbors_length - lookup->wordsize + 1;
  535.   Uint1* w = word;
  536.   Uint1 different;
  537.   Int4 score;
  538.   Int4 threshold = lookup->threshold;
  539.   Int4 i;
  540.   Int4* p0;
  541.   Int4* p1;
  542.   Int4* p2;
  543.   Int4 corrected_offset = offset + query_bias;
  544.   /* For each group of 'wordsize' bytes starting at 'w', 
  545.    * add the group to the lookup table at each offset 's' if
  546.    * either
  547.    *    - w matches s, or 
  548.    *    - the score derived from aligning w and s is high enough
  549.    */
  550.   switch (lookup->wordsize)
  551.     {
  552.       case 1:
  553. p0 = matrix[w[0]];
  554.         while (s < s_end)
  555.           {
  556.             if ( (s[0] == w[0]) || (p0[s[0]] >= threshold) )
  557.     {
  558.                 BlastAaLookupAddWordHit(lookup,s,corrected_offset);
  559. if (s[0] == w[0])
  560.     lookup->exact_matches++;
  561. else
  562.     lookup->neighbor_matches++;
  563.     }
  564.             s++;
  565.      }
  566.         break;
  567.       case 2:
  568. p0 = matrix[w[0]];
  569. p1 = matrix[w[1]];
  570.         while (s < s_end)
  571.           {
  572.             score = p0[s[0]] + p1[s[1]];
  573.     different = (w[0] ^ s[0]) | (w[1] ^ s[1]);
  574.   
  575.             if ( !different || (score >= threshold) )
  576.     {
  577.                 BlastAaLookupAddWordHit(lookup,s,corrected_offset);
  578. if (!different)
  579.     lookup->exact_matches++;
  580. else
  581.     lookup->neighbor_matches++;
  582.     }
  583.             s++;
  584.   }
  585.         break;
  586.       case 3:
  587. p0 = matrix[w[0]];
  588. p1 = matrix[w[1]];
  589. p2 = matrix[w[2]];
  590.         while (s < s_end)
  591.           {
  592.             score = p0[s[0]] + p1[s[1]] + p2[s[2]];
  593.     different = (w[0] ^ s[0]) | (w[1] ^ s[1]) | (w[2] ^ s[2]);
  594.   
  595.             if ( !different || (score >= threshold) )
  596.     {
  597.                 BlastAaLookupAddWordHit(lookup,s,corrected_offset);
  598. if (!different)
  599.     lookup->exact_matches++;
  600. else
  601.     lookup->neighbor_matches++;
  602.     }
  603.             s++;
  604.      }
  605.         break;
  606.       default:
  607.         while (s < s_end)
  608.           {
  609.             score = 0;
  610.             different = 0;
  611.             for (i = 0; i < lookup->wordsize; i++)
  612.               {
  613.                 score += matrix[w[i]][s[i]];
  614.                 different |= w[i] ^ s[i];
  615.               }
  616.   
  617.             if ( !different || (score >= threshold) )
  618.     {
  619.                 BlastAaLookupAddWordHit(lookup,s,corrected_offset);
  620. if (!different)
  621.     lookup->exact_matches++;
  622. else
  623.     lookup->neighbor_matches++;
  624.     }
  625.             s++;
  626.      }
  627.         break;
  628.     }
  629. }
  630. static void AddPSSMWordHits(LookupTable* lookup, Int4** matrix, 
  631.                             Int4 offset, Int4 query_bias)
  632. {
  633.   Uint1* s = lookup->neighbors;
  634.   Uint1* s_end=s + lookup->neighbors_length - lookup->wordsize;
  635.   Int4 score;
  636.   Int4 threshold = lookup->threshold;
  637.   Int4 i;
  638.   Int4* p0;
  639.   Int4* p1;
  640.   Int4* p2;
  641.   Int4 corrected_offset = offset + query_bias;
  642.   /* Equivalent to AddWordHits(), except that the word score
  643.    * is derived from a Position-Specific Scoring Matrix (PSSM) 
  644.    */
  645.   switch (lookup->wordsize)
  646.     {
  647.       case 1:
  648. p0 = matrix[offset];
  649.         while (s < s_end)
  650.           {
  651.             if (p0[s[0]] >= threshold)
  652.                 BlastAaLookupAddWordHit(lookup,s,corrected_offset);
  653.             s++;
  654.      }
  655.         break;
  656.       case 2:
  657. p0 = matrix[offset];
  658. p1 = matrix[offset+1];
  659.         while (s < s_end)
  660.           {
  661.             score = p0[s[0]] + p1[s[1]];
  662.   
  663.             if (score >= threshold)
  664.                 BlastAaLookupAddWordHit(lookup,s,corrected_offset);
  665.             s++;
  666.      }
  667.         break;
  668.       case 3:
  669. p0 = matrix[offset];
  670. p1 = matrix[offset + 1];
  671. p2 = matrix[offset + 2];
  672.         while (s < s_end)
  673.           {
  674.             score = p0[s[0]] + p1[s[1]] + p2[s[2]];
  675.   
  676.             if (score >= threshold)
  677.                 BlastAaLookupAddWordHit(lookup,s,corrected_offset);
  678.             s++;
  679.      }
  680.         break;
  681.       default:
  682.         while (s < s_end)
  683.           {
  684.             score = 0;
  685.             for(i=0;i<lookup->wordsize;i++)
  686.                 score += matrix[offset + i][s[i]];
  687.   
  688.             if (score >= threshold)
  689.                 BlastAaLookupAddWordHit(lookup,s,offset);
  690.             s++;
  691.      }
  692.         break;
  693.     }
  694. }
  695. /******************************************************
  696.  *
  697.  * Nucleotide BLAST specific functions and definitions
  698.  *
  699.  ******************************************************/
  700. /* Description in na_lookup.h */
  701. Int4 BlastNaScanSubject_AG(const LookupTableWrap* lookup_wrap,
  702.    const BLAST_SequenceBlk* subject,
  703.    Int4 start_offset,
  704.    Uint4* NCBI_RESTRICT q_offsets,
  705.    Uint4* NCBI_RESTRICT s_offsets,
  706.    Int4 max_hits,  
  707.        Int4* end_offset)
  708. {
  709.    LookupTable* lookup = (LookupTable*) lookup_wrap->lut;
  710.    Uint1* s;
  711.    Uint1* abs_start;
  712.    Int4  index=0, s_off;
  713.    
  714.    Int4* lookup_pos;
  715.    Int4 num_hits;
  716.    Int4 q_off;
  717.    PV_ARRAY_TYPE *pv_array = lookup->pv;
  718.    Int4 total_hits = 0;
  719.    Int4 compressed_wordsize, compressed_scan_step;
  720.    Boolean full_byte_scan = (lookup->scan_step % COMPRESSION_RATIO == 0);
  721.    Int4 i;
  722.    abs_start = subject->sequence;
  723.    s = abs_start + start_offset/COMPRESSION_RATIO;
  724.    compressed_scan_step = lookup->scan_step / COMPRESSION_RATIO;
  725.    compressed_wordsize = lookup->reduced_wordsize;
  726.    index = 0;
  727.    
  728.    /* NB: s in this function always points to the start of the word!
  729.     */
  730.    if (full_byte_scan) {
  731.       Uint1* s_end = abs_start + subject->length/COMPRESSION_RATIO - 
  732.          compressed_wordsize;
  733.       for ( ; s <= s_end; s += compressed_scan_step) {
  734.          index = 0;
  735.          for (i = 0; i < compressed_wordsize; ++i)
  736.             index = ((index)<<FULL_BYTE_SHIFT) | s[i];
  737.          
  738.          if (NA_PV_TEST(pv_array, index, PV_ARRAY_BTS)) {
  739.             num_hits = lookup->thick_backbone[index].num_used;
  740.             ASSERT(num_hits != 0);
  741.             if (num_hits > (max_hits - total_hits))
  742.                break;
  743.             if ( num_hits <= HITS_ON_BACKBONE )
  744.                /* hits live in thick_backbone */
  745.                lookup_pos = lookup->thick_backbone[index].payload.entries;
  746.             else
  747.                /* hits live in overflow array */
  748.                lookup_pos = & ( lookup->overflow[lookup->thick_backbone[index].payload.overflow_cursor] );
  749.             
  750.             s_off = (s - abs_start)*COMPRESSION_RATIO;
  751.             while (num_hits) {
  752.                q_off = *((Uint4 *) lookup_pos); /* get next query offset */
  753.                lookup_pos++;
  754.                num_hits--;
  755.                
  756.                q_offsets[total_hits] = q_off;
  757.                s_offsets[total_hits++] = s_off;
  758.             }
  759.          }
  760.       }
  761.       *end_offset = (s - abs_start)*COMPRESSION_RATIO;
  762.    } else {
  763.       Int4 reduced_word_length = compressed_wordsize*COMPRESSION_RATIO;
  764.       Int4 last_offset = subject->length - reduced_word_length;
  765.       Uint1 bit;
  766.       Int4 adjusted_index;
  767.       for (s_off = start_offset; s_off <= last_offset; 
  768.            s_off += lookup->scan_step) {
  769.          s = abs_start + (s_off / COMPRESSION_RATIO);
  770.          bit = 2*(s_off % COMPRESSION_RATIO);
  771.          /* Compute index for a word made of full bytes */
  772.          index = 0;
  773.          for (i = 0; i < compressed_wordsize; ++i)
  774.             index = ((index)<<FULL_BYTE_SHIFT) | (*s++);
  775.          adjusted_index = 
  776.             BlastNaLookupAdjustIndex(s, index, lookup->mask, bit);
  777.          
  778.          if (NA_PV_TEST(pv_array, adjusted_index, PV_ARRAY_BTS)) {
  779.             num_hits = lookup->thick_backbone[adjusted_index].num_used;
  780.             ASSERT(num_hits != 0);
  781.             if (num_hits > (max_hits - total_hits))
  782.                break;
  783.             if ( num_hits <= HITS_ON_BACKBONE )
  784.                /* hits live in thick_backbone */
  785.                lookup_pos = lookup->thick_backbone[adjusted_index].payload.entries;
  786.             else
  787.                /* hits live in overflow array */
  788.                lookup_pos = & (lookup->overflow [ lookup->thick_backbone[adjusted_index].payload.overflow_cursor]);
  789.             
  790.             while (num_hits) {
  791.                q_off = *((Uint4 *) lookup_pos); /* get next query offset */
  792.                lookup_pos++;
  793.                num_hits--;
  794.                
  795.                q_offsets[total_hits] = q_off;
  796.                s_offsets[total_hits++] = s_off;
  797.             }
  798.          }
  799.       }
  800.       *end_offset = s_off;
  801.    }
  802.    return total_hits;
  803. }
  804. /* Description in na_lookup.h */
  805. Int4 BlastNaScanSubject(const LookupTableWrap* lookup_wrap,
  806.        const BLAST_SequenceBlk* subject, Int4 start_offset,
  807.        Uint4* q_offsets, Uint4* s_offsets, Int4 max_hits, 
  808.        Int4* end_offset)
  809. {
  810.    Uint1* s;
  811.    Uint1* abs_start,* s_end;
  812.    Int4  index=0, s_off;
  813.    LookupTable* lookup = (LookupTable*) lookup_wrap->lut;
  814.    Int4* lookup_pos;
  815.    Int4 num_hits;
  816.    Int4 q_off;
  817.    PV_ARRAY_TYPE *pv_array = lookup->pv;
  818.    Int4 total_hits = 0;
  819.    Int4 reduced_word_length = lookup->reduced_wordsize*COMPRESSION_RATIO;
  820.    Int4 i;
  821.    abs_start = subject->sequence;
  822.    s = abs_start + start_offset/COMPRESSION_RATIO;
  823.    /* s_end points to the place right after the last full sequence byte */ 
  824.    s_end = 
  825.       abs_start + (*end_offset + reduced_word_length)/COMPRESSION_RATIO;
  826.    index = 0;
  827.    
  828.    /* Compute the first index */
  829.    for (i = 0; i < lookup->reduced_wordsize; ++i)
  830.       index = ((index)<<FULL_BYTE_SHIFT) | *s++;
  831.    /* s points to the byte right after the end of the current word */
  832.    while (s <= s_end) {
  833.       if (NA_PV_TEST(pv_array, index, PV_ARRAY_BTS)) {
  834.          num_hits = lookup->thick_backbone[index].num_used;
  835.          ASSERT(num_hits != 0);
  836.          if (num_hits > (max_hits - total_hits))
  837.             break;
  838.          if ( num_hits <= HITS_ON_BACKBONE )
  839.             /* hits live in thick_backbone */
  840.             lookup_pos = lookup->thick_backbone[index].payload.entries;
  841.          else
  842.             /* hits live in overflow array */
  843.             lookup_pos = & (lookup->overflow[lookup->thick_backbone[index].payload.overflow_cursor]);
  844.          
  845.          /* Save the hits offsets */
  846.          s_off = (s - abs_start)*COMPRESSION_RATIO - reduced_word_length;
  847.          while (num_hits) {
  848.             q_off = *((Uint4 *) lookup_pos); /* get next query offset */
  849.             lookup_pos++;
  850.             num_hits--;
  851.             
  852.             q_offsets[total_hits] = q_off;
  853.             s_offsets[total_hits++] = s_off;
  854.          }
  855.       }
  856.       /* Compute the next value of the index */
  857.       index = (((index)<<FULL_BYTE_SHIFT) & lookup->mask) | (*s++);  
  858.    }
  859.    /* Ending offset should point to the start of the word that ends 
  860.       at s */
  861.    *end_offset = (s - abs_start)*COMPRESSION_RATIO - reduced_word_length;
  862.    return total_hits;
  863. }
  864. LookupTable* LookupTableDestruct(LookupTable* lookup)
  865. {
  866.    sfree(lookup->thick_backbone);
  867.    sfree(lookup->overflow);
  868.    sfree(lookup->pv);
  869.    sfree(lookup);
  870.    return NULL;
  871. }
  872. RPSLookupTable* RPSLookupTableDestruct(RPSLookupTable* lookup)
  873. {
  874.    /* The following will only free memory that was 
  875.       allocated by RPSLookupTableNew. */
  876.    sfree(lookup->rps_pssm);
  877.    sfree(lookup->pv);
  878.    sfree(lookup);
  879.    return NULL;
  880. }
  881. /** Add a word information to the lookup table 
  882.  * @param lookup Pointer to the lookup table structure [in] [out]
  883.  * @param w Pointer to the start of a word [in]
  884.  * @param query_offset Offset into the query sequence where this word ends [in]
  885.  */
  886. static Int4 BlastNaLookupAddWordHit(LookupTable* lookup, Uint1* w,
  887.                                     Int4 query_offset)
  888. {
  889.   Int4 index=0;
  890.   Int4 chain_size = 0; /* Total number of elements in the chain */
  891.   Int4 hits_in_chain = 0; /* Number of occupied elements in the chain, not 
  892.                              including the zeroth and first positions */ 
  893.   Int4* chain = NULL;
  894.   /* compute its index */
  895.   if (Na_LookupComputeIndex(lookup, w, &index) == -1)
  896.      /* Word contains ambiguities, skip it */
  897.      return 0;
  898.   ASSERT(index < lookup->backbone_size);
  899.       
  900.   /* If backbone cell is null, initialize a new chain */
  901.   if (lookup->thin_backbone[index] == NULL)
  902.     {
  903.       chain_size = 8;
  904.       hits_in_chain = 0;
  905.       chain = calloc( chain_size, sizeof(Int4) );
  906.       ASSERT(chain != NULL);
  907.       chain[0] = chain_size;
  908.       chain[1] = hits_in_chain;
  909.       lookup->thin_backbone[index] = chain;
  910.     }
  911.   else
  912.     /* Otherwise, use the existing chain */
  913.     {
  914.       chain = lookup->thin_backbone[index];
  915.       chain_size = chain[0];
  916.       hits_in_chain = chain[1];
  917.     }
  918.   
  919.   /* If the chain is full, allocate more room */
  920.   if ( (hits_in_chain + 2) == chain_size )
  921.     {
  922.       chain_size = chain_size * 2;
  923.       chain = realloc(chain, chain_size * sizeof(Int4) );
  924.       ASSERT(chain != NULL);
  925.       lookup->thin_backbone[index] = chain;
  926.       chain[0] = chain_size;
  927.     }
  928.   
  929.   /* Add the hit */
  930.   chain[ chain[1] + 2 ] = query_offset;
  931.   chain[1] += 1;
  932.   return 0;
  933. }
  934. /* See description in blast_lookup.h */
  935. Int4 BlastNaLookupIndexQuery(LookupTable* lookup, BLAST_SequenceBlk* query,
  936. ListNode* location)
  937. {
  938.   ListNode* loc;
  939.   Int4 from, to;
  940.   Int4 offset;
  941.   Uint1* sequence;
  942.   for(loc=location; loc; loc=loc->next) {
  943.      from = ((SSeqRange*) loc->ptr)->left;
  944.      to = ((SSeqRange*) loc->ptr)->right + 1;
  945.      
  946.      sequence = query->sequence + from;
  947.      /* Last offset is such that full word fits in the sequence */
  948.      to -= lookup->reduced_wordsize*COMPRESSION_RATIO;
  949.      for(offset = from; offset <= to; offset++) {
  950. BlastNaLookupAddWordHit(lookup, sequence, offset);
  951. ++sequence;
  952.      }
  953.   }
  954.   return 0;
  955. }