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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: blast_kappa.c,v $
  4.  * PRODUCTION Revision 1000.0  2004/06/01 18:13:48  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [GCC34_MSVC7] Dev-tree R1.10
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: blast_kappa.c,v 1000.0 2004/06/01 18:13:48 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.  * Authors: Alejandro Schaffer, Mike Gertz (ported to algo/blast by Tom Madden)
  35.  *
  36.  */
  37. /** @file blast_kappa.c
  38.  * Utilities for doing Smith-Waterman alignments and adjusting the scoring 
  39.  * system for each match in blastpgp
  40.  */
  41. static char const rcsid[] = 
  42.     "$Id: blast_kappa.c,v 1000.0 2004/06/01 18:13:48 gouriano Exp $";
  43. #include <algo/blast/core/blast_def.h>
  44. #include <algo/blast/core/blast_hits.h>
  45. #include <algo/blast/core/blast_stat.h>
  46. #include <algo/blast/core/blast_kappa.h>
  47. #include <algo/blast/core/blast_util.h>
  48. #include <algo/blast/core/blast_gapalign.h>
  49. #include <algo/blast/core/blast_traceback.h>
  50. #include <algo/blast/core/blast_filter.h>
  51. #include "blast_psi_priv.h"
  52. #include "matrix_freq_ratios.h"
  53. #include "blast_gapalign_pri.h"
  54. #define EVALUE_STRETCH 5 /*by what factor might initially reported E-value
  55.                            exceed true Evalue*/
  56. #define PRO_TRUE_ALPHABET_SIZE 20
  57. #define scoreRange 10000
  58. #define XCHAR   21    /*character for low-complexity columns*/
  59. #define STARCHAR   25    /*character for stop codons*/
  60. /*positions of true characters in protein alphabet*/
  61. Int4 trueCharPositions[20] = {1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,22};
  62. /** Structure used for full Smith-Waterman results. 
  63. */
  64. typedef struct SWResults {
  65.     struct SWResults *next;    /**< next object in list */
  66.     Uint1* seq;                /**< match sequence. */
  67.     Int4 seqStart;             /**< start of alignment on match */
  68.     Int4 seqEnd;               /**< end of alignment on match */
  69.     Int4 queryStart;           /**< start of alignment on query */
  70.     Int4 queryEnd;             /**< end of alignment on query */
  71.     Int4 score;                /**< score of alignment */
  72.     double eValue;             /**< best expect value for this match record */
  73.     double eValueThisAlign;    /**< expect value of this alignment. */
  74.     double Lambda;             /**< Karlin-Altschul parameter. */
  75.     double logK;               /**< log of Karlin-Altschul parameter */
  76.     Boolean isFirstAlignment;  /**< TRUE if first alignment for this sequence */
  77.     Int4 subject_index;        /**< ordinal ID of match sequence, needed to break 
  78.                                   ties on rare occasions */
  79.     BlastHSP* hsp;             /**< Saves alignment informaiton for conversion to SeqAlign. */
  80. } SWResults;
  81. /**
  82.  * Frees the linked-list of SWResults.  Does not deallocate the BlastHSP 
  83.  * on the SWResults as that is saved elsewhere.
  84.  * @param sw_results the head of the linked list to be freed [in]
  85.  * @return NULL pointer 
  86. */
  87. static SWResults* SWResultsFree(SWResults* sw_results)
  88. {
  89.     SWResults *current, *next;
  90.     next = current = sw_results;
  91.     while (current)
  92.     {
  93.        next = current->next;
  94.        sfree(current);
  95.        current = next;
  96.     }
  97.     return NULL;
  98. }
  99. /**
  100.  * SWResultsNew Create a new instance of the SWResults struct, initializing
  101.  *              it with values common to different kinds of searches 
  102.  *              The parameters of this function correspond directly to fields
  103.  *              in the SWResults data structure.
  104.  * @param sequence match sequence [in]
  105.  * @param score score of match [in]
  106.  * @param newEvalue expect value of this alignment [in]
  107.  * @param bestEvalue lowest expect value of this match sequence [in]
  108.  * @param isFirstAlignment TRUE if first alignment for this sequence [in]
  109.  * @param lambda Karlin-Altschul parameter [in]
  110.  * @param logK log of Karlin-Altschul parameter [in]
  111.  * @param subject_index ordinal ID of match sequence [in]
  112.  */
  113. static SWResults *
  114. SWResultsNew(Uint1* sequence,
  115.              Int4 score,
  116.              double newEvalue,
  117.              double bestEvalue,
  118.              Boolean isFirstAlignment,
  119.              double lambda,
  120.              double logK,
  121.              Int4 subject_index)
  122. {
  123.   SWResults *newSW;             /* The newly created instance of SWResults */
  124.   newSW = (SWResults *) calloc(1, sizeof(SWResults));
  125.   if(newSW) {
  126.     newSW->seq     = sequence;
  127.     newSW->score   = score;
  128.     newSW->eValue  = bestEvalue;
  129.     newSW->Lambda  = lambda;
  130.     newSW->logK    = logK;
  131.     newSW->eValueThisAlign  = newEvalue;
  132.     newSW->isFirstAlignment = isFirstAlignment;
  133.     newSW->subject_index    = subject_index;
  134.     newSW->next = NULL;
  135.   }
  136.   return newSW;
  137. }
  138. /**
  139.  * An instance of struct Kappa_MatchRecord represents all alignments
  140.  * of a query sequence to a matching subject sequence.
  141.  *
  142.  * For a given query-subject pair, a Kappa_MatchRecord is created once it
  143.  * is known that the eValue of the best alignment is small enough to be 
  144.  * significant.  Then alignments of the two sequences are added to the
  145.  * Kappa_MatchRecord one at a time, using one of the following two routines
  146.  * 
  147.  * - Kappa_MatchRecordInsertHSP inserts the alignment represented
  148.  *   by a single HSP into the match record.
  149.  * - Kappa_MatchRecordInsertSwAlign inserts an alignment computed by
  150.  *   the Smith-Waterman algorithm into the match record.
  151.  * 
  152.  * Alignments should be specified in order of smallest (best) e-value to
  153.  * largest (worst) e-value.
  154.  *
  155.  * The Kappa_MatchRecord::alignments field stores the alignments in
  156.  * the reverse order, i.e. from largest (worst) e-value to smallest
  157.  * (best) e-value.  The reason the alignments are stored in reverse
  158.  * order is that this order is consistent with the order that matches
  159.  * are returned by a SWheap (see below), i.e. worst to best. 
  160.  */ 
  161. struct Kappa_MatchRecord {
  162.   double  eValue;          /**< best evalue of all alignments the record */
  163.   Int4  score;           /**< best score of all alignments the record */  
  164.   Uint1*     sequence;        /**< the subject sequence */
  165.   Int4         subject_index;   /**< the index number of the subject sequence */
  166.   SWResults   *alignments;      /**< a list of query-subject alignments */
  167. };
  168. typedef struct Kappa_MatchRecord Kappa_MatchRecord;
  169. /** Initialize a Kappa_MatchRecord.  Parameters to this function correspond
  170.  *    directly to fields of Kappa_MatchRecord. 
  171.  * @param self the record to be modified [in][out]
  172.  * @param eValue expect value of this alignment [in]
  173.  * @param score score of match [in]
  174.  * @param sequence match sequence [in]
  175.  * @param subject_index ordinal ID of sequence in database [in]
  176.  */
  177. static void
  178. Kappa_MatchRecordInitialize(Kappa_MatchRecord * self,
  179.                             double eValue,
  180.                             Int4 score,
  181.                             Uint1* sequence,
  182.                             Int4 subject_index)
  183. {
  184.   self->eValue   = eValue;
  185.   self->score    = score;
  186.   self->sequence = sequence;
  187.   self->subject_index = subject_index;
  188.   self->alignments    = NULL;
  189. }
  190. /** The following procedure computes the number of identities in an
  191.  *    alignment of query_seq to the matching sequence stored in
  192.  *    SWAlign. The alignment is encoded in gap_info
  193.  * @param SWAlign input structure holding HSP to be modified [in][out]
  194.  * @param query_seq Query sequence used for calculation [in]
  195.  */
  196. static Int2 SWAlignGetNumIdentical(SWResults *SWAlign, Uint1* query_seq)
  197. {
  198.    Int4 num_ident; /*number of identities to return*/
  199.    Int4 align_length; /*aligned length, calculated but discarded. */
  200.    Blast_HSPGetNumIdentities(query_seq, SWAlign->seq, 
  201.       SWAlign->hsp, TRUE, &num_ident, &align_length);
  202.    
  203.    SWAlign->hsp->num_ident = num_ident;
  204.    return 0;
  205. }
  206. /**  
  207.  * Insert an alignment represented by a seqAlign into the match
  208.  *    record.
  209.  * @param self the match record to be modified [in][out]
  210.  * @param hsp contains alignment and scoring information, 
  211.  *    will be NULLed out [in][out]
  212.  * @param lambda a statistical parameter used to evaluate the significance of the
  213.  *    match [in]
  214.  * @param logK a statistical parameter used to evaluate the significance of the
  215.  *    match [in]
  216.  * @param localScalingFactor the factor by which the scoring system has been
  217.  *    scaled in order to obtain greater precision [in]
  218.  * @param query_seq Used to calculate percent identity [in]
  219.  */
  220. static void
  221. Kappa_MatchRecordInsertHSP(
  222.   Kappa_MatchRecord * self,     
  223.   BlastHSP* *hsp,         
  224.   double lambda,           
  225.   double logK,             
  226.   double localScalingFactor,
  227.   Uint1* query_seq
  228. ) {
  229.   SWResults *newSW;             /* A new SWResults object that
  230.                                    represents the alignment to be
  231.                                    inserted */
  232.   newSW =
  233.     SWResultsNew(self->sequence, self->score, 
  234.                  (*hsp)->evalue, self->eValue, (Boolean) (NULL == self->alignments),
  235.                  localScalingFactor * lambda, logK,
  236.                  self->subject_index);
  237.   newSW->queryStart = (*hsp)->gap_info->start1;
  238.   newSW->seqStart   = (*hsp)->gap_info->start2;
  239.   newSW->hsp   = *hsp;
  240.   *hsp = NULL; /* Information stored on SWResults now. */
  241.   SWAlignGetNumIdentical(newSW, query_seq); /* Calculate num identities, attach to HSP. */
  242.   newSW->next       = self->alignments;
  243.   self->alignments = newSW;
  244. }
  245. /**  
  246.  * Insert an alignment computed by the Smith-Waterman algorithm into
  247.  *    the match record.
  248.  * @param self the match record to be modified [in][out]
  249.  * @param newScore the score of the alignment [in]
  250.  * @param newEvalue the expect value of the alignment [in]
  251.  * @param lambda a statistical parameter used to evaluate the significance of the
  252.  *    match [in]
  253.  * @param logK a statistical parameter used to evaluate the significance of the
  254.  *    match [in]
  255.  * @param localScalingFactor the factor by which the scoring system has been
  256.  *    scaled in order to obtain greater precision [in]
  257.  * @param matchStart start of the alignment in the subject [in]
  258.  * @param matchAlignmentExtent length of the alignment in the subject [in]
  259.  * @param queryStart start of the alignment in the query [in]
  260.  * @param queryAlignmentExtent length of the alignment in the query [in]
  261.  * @param reverseAlignScript Alignment information (script) returned by 
  262.  *    the X-drop alignment algorithm [in]
  263.  * @param query_seq Used to calculate percent identity [in]
  264.  */
  265. static void
  266. Kappa_MatchRecordInsertSwAlign(
  267.   Kappa_MatchRecord * self,     
  268.   Int4 newScore,         
  269.   double newEvalue,        
  270.   double lambda,           
  271.   double logK,
  272.   double localScalingFactor,
  273.   Int4 matchStart,
  274.   Int4 matchAlignmentExtent,
  275.   Int4 queryStart,
  276.   Int4 queryAlignmentExtent,
  277.   Int4 * reverseAlignScript,
  278.   Uint1* query_seq
  279. ) {
  280.   SWResults *newSW;             /* A new SWResults object that
  281.                                    represents the alignment to be
  282.                                    inserted */
  283.   GapEditBlock* editBlock=NULL; /* Contains representation of traceback. */
  284.   if(NULL == self->alignments) {
  285.     /* This is the first sequence recorded for this match. Use the x-drop
  286.      * score, "newScore", as the score for the sequence */
  287.     self->score = newScore;
  288.   }
  289.   newSW =
  290.     SWResultsNew(self->sequence, self->score, newEvalue,
  291.                  self->eValue, (Boolean) (NULL == self->alignments),
  292.                  lambda * localScalingFactor, logK, self->subject_index);
  293.   newSW->seqStart   = matchStart;
  294.   newSW->seqEnd     = matchStart + matchAlignmentExtent;
  295.   newSW->queryStart = queryStart;
  296.   newSW->queryEnd   = queryStart + queryAlignmentExtent;
  297.   newSW->next       = self->alignments;
  298.   BLAST_TracebackToGapEditBlock(reverseAlignScript, queryAlignmentExtent, matchAlignmentExtent, 
  299.      queryStart, matchStart, &editBlock);
  300.  
  301.   Blast_HSPInit(queryStart, queryStart + queryAlignmentExtent,
  302.                 matchStart, matchStart + matchAlignmentExtent,
  303.                 0, 0, 0, 0, newScore, &editBlock, &(newSW->hsp));
  304.   newSW->hsp->evalue = newEvalue;
  305.  
  306.   SWAlignGetNumIdentical(newSW, query_seq); /* Calculate num identities, attach to HSP. */
  307.   self->alignments  = newSW;
  308. }
  309. /**
  310.  * The struct SWheapRecord data type is used below to define the
  311.  * internal structure of a SWheap (see below).  A SWheapRecord
  312.  * represents all alignments of a query sequence to a particular
  313.  * matching sequence.
  314.  *
  315.  * The SWResults::theseAlignments field is a linked list of alignments
  316.  * of the query-subject pair.  The list is ordered by evalue in
  317.  * descending order. Thus the first element has biggest (worst) evalue
  318.  * and the last element has smallest (best) evalue. 
  319.  */
  320. typedef struct SWheapRecord {
  321.   double bestEvalue;       /* best (smallest) evalue of all alignments
  322.                                  * in the record */
  323.   SWResults *theseAlignments;   /* a list of alignments */
  324. } SWheapRecord;
  325. /**  Compare two records in the heap.  
  326.  * @param place1 the first record to be compared [in]
  327.  * @param place2 the other record to be compared [in]
  328.  */
  329. static Boolean
  330. SWheapRecordCompare(SWheapRecord * place1,
  331.                     SWheapRecord * place2)
  332. {
  333.   return ((place1->bestEvalue > place2->bestEvalue) ||
  334.           (place1->bestEvalue == place2->bestEvalue &&
  335.            place1->theseAlignments->subject_index >
  336.            place2->theseAlignments->subject_index));
  337. }
  338. /**  swap two records in the heap
  339.  * @param heapArray holds the records to be swapped [in][out]
  340.  * @param i the first record to be swapped [in]
  341.  * @param j the other record to be swapped [in]
  342.  */
  343. static void
  344. SWheapRecordSwap(SWheapRecord * heapArray,
  345.                  Int4 i,
  346.                  Int4 j)
  347. {
  348.   /* bestEvalue and theseAlignments are temporary variables used to
  349.    * perform the swap. */
  350.   double bestEvalue       = heapArray[i].bestEvalue;
  351.   SWResults *theseAlignments   = heapArray[i].theseAlignments;
  352.   heapArray[i].bestEvalue      = heapArray[j].bestEvalue;
  353.   heapArray[i].theseAlignments = heapArray[j].theseAlignments;
  354.   heapArray[j].bestEvalue      = bestEvalue;
  355.   heapArray[j].theseAlignments = theseAlignments;
  356. }
  357. #ifdef KAPPA_INTENSE_DEBUG
  358. /**
  359.  * Verifies that the array heapArray[i] .. heapArray[n] is ordered so
  360.  * as to be a valid heap.  This routine checks every element in the array,
  361.  * an so is very time consuming.  It is for debugging purposes only.
  362.  */
  363. static Boolean
  364. SWheapIsValid(SWheapRecord * heapArray,
  365.               Int4 i,
  366.               Int4 n)
  367. {
  368.   /* indices of nodes to the left and right of node i */
  369.   Int4 left = 2 * i, right = 2 * i + 1;        
  370.   if(right <= n) {
  371.     return !SWheapRecordCompare(&(heapArray[right]), &(heapArray[i])) &&
  372.       SWheapIsValid(heapArray, right, n);
  373.   }
  374.   if(left <= n) {
  375.     return !SWheapRecordCompare(&(heapArray[left]), &(heapArray[i])) &&
  376.       SWheapIsValid(heapArray, left, n);
  377.   }
  378.   return TRUE;
  379. }
  380. #define KAPPA_ASSERT(expr) ((expr) ? 0 : 
  381. (fprintf( stderr, "KAPPA_ASSERT failed line %d: %s", __LINE__, #expr ), 
  382. exit(1)))
  383. #else
  384. #define KAPPA_ASSERT(expr) (void)(0)
  385. #endif
  386. /** On entry, all but the first element of the array heapArray[i]
  387.  * .. heapArray[n] are in valid heap order.  This routine rearranges
  388.  * the elements so that on exit they all are in heap order. 
  389.  * @param heapArray holds the heap [in][out]
  390.  * @param i ?? [in]
  391.  * @param n ?? [in]
  392.  */
  393. static void
  394. SWheapifyDown(SWheapRecord * heapArray,
  395.               Int4 i,
  396.               Int4 n)
  397. {
  398.   Boolean moreswap = TRUE;      /* is more swapping needed */
  399.   Int4 left, right, largest;    /* placeholders for indices in swapping */
  400.   do {
  401.     left  = 2 * i;
  402.     right = 2 * i + 1;
  403.     if((left <= n) &&
  404.        (SWheapRecordCompare(&(heapArray[left]), &(heapArray[i]))))
  405.       largest = left;
  406.     else
  407.       largest = i;
  408.     if((right <= n) &&
  409.        (SWheapRecordCompare(&(heapArray[right]), &(heapArray[largest]))))
  410.       largest  = right;
  411.     if(largest != i) {
  412.       SWheapRecordSwap(heapArray, i, largest);
  413.       /* push largest up the heap */
  414.       i       = largest;       /* check next level down */
  415.     } else
  416.       moreswap = FALSE;
  417.   } while(moreswap);            /* function builds the heap */
  418.   KAPPA_ASSERT(SWheapIsValid(heapArray, i, n));
  419. }
  420. /** On entry, all but the last element of the array heapArray[i]
  421.  *   .. heapArray[n] are in valid heap order.  This routine rearranges
  422.  *   the elements so that on exit they all are in heap order.
  423.  * @param heapArray holds the heap [in][out]
  424.  * @param i the largest element to work with [in]
  425.  * @param n the largest element in the heap [in]
  426.  */
  427. static void
  428. SWheapifyUp(SWheapRecord * heapArray,
  429.             Int4 i,
  430.             Int4 n)
  431. {
  432.   Int4 parent = i / 2;          /* index to the node that is the
  433.                                    parent of node i */
  434.   while(parent >= 1 &&
  435.         SWheapRecordCompare(&(heapArray[i]), &(heapArray[parent]))){
  436.     SWheapRecordSwap(heapArray, i, parent);
  437.     i       = parent;
  438.     parent /= 2;
  439.   }
  440.   KAPPA_ASSERT(SWheapIsValid(heapArray, 1, n));
  441. }
  442. /** A SWheap represents a collection of alignments between one query
  443.  * sequence and several matching subject sequences.  
  444.  *
  445.  * Each matching sequence is allocated one record in a SWheap.  The
  446.  * eValue of a query-subject pair is the best (smallest positive)
  447.  * evalue of all alignments between the two sequences.
  448.  * 
  449.  * A match will be inserted in the the SWheap if:
  450.  * - there are fewer that SWheap::heapThreshold elements in the SWheap;
  451.  * - the eValue of the match is <= SWheap::ecutoff; or
  452.  * - the eValue of the match is less than the largest (worst) eValue
  453.  *   already in the SWheap.
  454.  *
  455.  * If there are >= SWheap::heapThreshold matches already in the SWheap
  456.  * when a new match is to be inserted, then the match with the largest
  457.  * (worst) eValue is removed, unless the largest eValue <=
  458.  * SWheap::ecutoff.  Matches with eValue <= SWheap::ecutoff are never
  459.  * removed by the insertion routine.  As a consequence, the SWheap can
  460.  * hold an arbitrarily large number of matches, although it is
  461.  * atypical for the number of matches to be greater than
  462.  * SWheap::heapThreshold.
  463.  *
  464.  * Once all matches have been collected, the SWheapToFlatList routine
  465.  * may be invoked to return a list of all alignments. (see below).
  466.  *
  467.  * While the number of elements in a heap < SWheap::heapThreshold, the
  468.  * SWheap is implemented as an unordered array, rather than a
  469.  * heap-ordered array.  The SWheap is converted to a heap-ordered
  470.  * array as soon as it becomes necessary to order the matches by
  471.  * evalue.  The routines that operate on a SWheap should behave
  472.  * properly whichever state the SWheap is in.
  473.  */
  474. struct SWheap {
  475.   Int4 n;                       /**< The current number of elements */
  476.   Int4 capacity;                /**< The maximum number of elements that may be 
  477.                                    inserted before the SWheap must be resized */
  478.   Int4 heapThreshold;           /**< see above */
  479.   double ecutoff;          /**< matches with evalue below ecutoff may
  480.                                    always be inserted in the SWheap */
  481.   double worstEvalue;      /**< the worst (biggest) evalue currently in
  482.                                    the heap */
  483.   SWheapRecord *array;          /**< the SWheapRecord array if the SWheap is
  484.                                    being represented as an unordered array */
  485.   SWheapRecord *heapArray;      /**< the SWheapRecord array if the SWheap is
  486.                                    being represented as an heap-ordered
  487.                                    array. At least one of (array, heapArray)
  488.                                    is NULL */
  489. };
  490. typedef struct SWheap SWheap;
  491. /** Convert a SWheap from a representation as an unordered array to
  492.  *    a representation as a heap-ordered array. 
  493.  * @param self record to be modified [in][out]
  494.  */
  495. static void
  496. ConvertToHeap(SWheap * self)
  497. {
  498.   if(NULL != self->array) {
  499.     Int4 i;                     /* heap node index */
  500.     Int4 n;                     /* number of elements in the heap */
  501.     /* We aren't already a heap */
  502.     self->heapArray = self->array;
  503.     self->array     = NULL;
  504.     n = self->n;
  505.     for(i = n / 2; i >= 1; --i) {
  506.       SWheapifyDown(self->heapArray, i, n);
  507.     }
  508.   }
  509.   KAPPA_ASSERT(SWheapIsValid(self->heapArray, 1, self->n));
  510. }
  511. /*When the heap is about to exceed its capacity, it will be grown by
  512.  *the minimum of a multiplicative factor of SWHEAP_RESIZE_FACTOR
  513.  *and an additive factor of SWHEAP_MIN_RESIZE. The heap never
  514.  *decreases in size */
  515. #define SWHEAP_RESIZE_FACTOR 1.5
  516. #define SWHEAP_MIN_RESIZE 100
  517. /** Return true if self would insert a match that had the given eValue 
  518.  * @param self record to be modified [in][out]
  519.  * @param eValue specified expect value [in]
  520.  */
  521. static Boolean
  522. SWheapWouldInsert(SWheap * self,
  523.                   double eValue)
  524. {
  525.   return self->n < self->heapThreshold ||
  526.     eValue <= self->ecutoff ||
  527.     eValue < self->worstEvalue;
  528. }
  529. /** Try to insert matchRecord into the SWheap. The alignments stored in
  530.  * matchRecord are used directly, i.e. they are not copied, but are
  531.  * rather stored in the SWheap or deleted
  532.  * @param self record to be modified [in][out]
  533.  * @param matchRecord record to be inserted [in]
  534.  */
  535. static void
  536. SWheapInsert(SWheap * self,
  537.              Kappa_MatchRecord * matchRecord)
  538. {
  539.   if(self->array && self->n >= self->heapThreshold) {
  540.     ConvertToHeap(self);
  541.   }
  542.   if(self->array != NULL) {
  543.     /* "self" is currently a list. Add the new alignments to the end */
  544.     SWheapRecord *heapRecord;   /* destination for the new alignments */ 
  545.     heapRecord                  = &self->array[++self->n];
  546.     heapRecord->bestEvalue      = matchRecord->eValue;
  547.     heapRecord->theseAlignments = matchRecord->alignments;
  548.     if( self->worstEvalue < matchRecord->eValue ) {
  549.       self->worstEvalue = matchRecord->eValue;
  550.     }
  551.   } else {                      /* "self" is currently a heap */
  552.     if(self->n < self->heapThreshold ||
  553.        (matchRecord->eValue <= self->ecutoff &&
  554.         self->worstEvalue <= self->ecutoff)) {
  555.       SWheapRecord *heapRecord; /* Destination for the new alignments */
  556.       /* The new alignments must be inserted into the heap, and all old
  557.        * alignments retained */
  558.       if(self->n >= self->capacity) {
  559.         /* The heap must be resized */
  560.         Int4 newCapacity;       /* capacity the heap will have after
  561.                                  * it is resized */
  562.         newCapacity      = MAX(SWHEAP_MIN_RESIZE + self->capacity,
  563.                                (Int4) (SWHEAP_RESIZE_FACTOR * self->capacity));
  564.         self->heapArray  = (SWheapRecord *)
  565.           realloc(self->heapArray, (newCapacity + 1) * sizeof(SWheapRecord));
  566.         self->capacity   = newCapacity;
  567.       }
  568.       /* end if the heap must be resized */
  569.       heapRecord    = &self->heapArray[++self->n];
  570.       heapRecord->bestEvalue      = matchRecord->eValue;
  571.       heapRecord->theseAlignments = matchRecord->alignments;
  572.       SWheapifyUp(self->heapArray, self->n, self->n);
  573.     } else {
  574.       /* Some set of alignments must be discarded */
  575.       SWResults *discardedAlignments = NULL;      /* alignments that
  576.                                                    * will be discarded
  577.                                                    * so that the new
  578.                                                    * alignments may be
  579.                                                    * inserted. */
  580.       if(matchRecord->eValue >= self->worstEvalue) {
  581.         /* the new alignments must be discarded */
  582.         discardedAlignments = matchRecord->alignments;
  583.       } else {
  584.         /* the largest element in the heap must be discarded */
  585.         SWheapRecord *heapRecord;     /* destination for the new alignments */
  586.         discardedAlignments         = self->heapArray[1].theseAlignments;
  587.         heapRecord                  = &self->heapArray[1];
  588.         heapRecord->bestEvalue      = matchRecord->eValue;
  589.         heapRecord->theseAlignments = matchRecord->alignments;
  590.         SWheapifyDown(self->heapArray, 1, self->n);
  591.       }
  592.       /* end else the largest element in the heap must be discarded */
  593.       while(discardedAlignments != NULL) {
  594.         /* There are discarded alignments that have not been freed */
  595.         SWResults *thisAlignment;     /* the head of the list of
  596.                                        * discarded alignments */
  597.         thisAlignment        = discardedAlignments;
  598.         discardedAlignments  = thisAlignment->next;
  599.         sfree(thisAlignment);
  600.       }
  601.       /* end while there are discarded alignments that have not been freed */
  602.     } 
  603.     /* end else some set of alignments must be discarded */
  604.     
  605.     self->worstEvalue = self->heapArray[1].bestEvalue;
  606.     KAPPA_ASSERT(SWheapIsValid(self->heapArray, 1, self->n));
  607.   }
  608.   /* end else "self" is currently a heap. */
  609.   /* The matchRecord->alignments pointer is no longer valid */
  610.   matchRecord->alignments = NULL;
  611. }
  612. /** Return true if only matches with evalue <= self->ecutoff 
  613.  *  may be inserted. 
  614.  * @param self heap containing data [in]
  615.  */
  616. static Boolean
  617. SWheapWillAcceptOnlyBelowCutoff(SWheap * self)
  618. {
  619.   return self->n >= self->heapThreshold && self->worstEvalue <= self->ecutoff;
  620. }
  621. /** Initialize a new SWheap; parameters to this function correspond
  622.  * directly to fields in the SWheap 
  623.  * @param self the object to be filled [in|out]
  624.  * @param capacity size of heap [in]
  625.  * @param heapThreshold  items always inserted if fewer than this number in heap [in]
  626.  * @param ecutoff items with a expect value less than this will always be inserted into heap [in]
  627.  */
  628. static void
  629. SWheapInitialize(SWheap * self,
  630.                  Int4 capacity,
  631.                  Int4 heapThreshold,
  632.                  double ecutoff)
  633. {
  634.   self->n             = 0;
  635.   self->heapThreshold = heapThreshold;
  636.   self->ecutoff       = ecutoff;
  637.   self->heapArray     = NULL;
  638.   self->capacity      = 0;
  639.   self->worstEvalue   = 0;
  640.   /* Begin life as a list */
  641.   self->array =
  642.     (SWheapRecord *) calloc(1, (capacity + 1) * sizeof(SWheapRecord));
  643.   self->capacity      = capacity;
  644. }
  645. /** Release the storage associated with the fields of a SWheap. Don't
  646.  * delete the SWheap structure itself.
  647.  * @param self record to be cleared [in][out]
  648.  */
  649. static void
  650. SWheapRelease(SWheap * self)
  651. {
  652.   if(self->heapArray) free(self->heapArray);
  653.   if(self->array) free(self->array);
  654.   self->n = self->capacity = self->heapThreshold = 0;
  655.   self->heapArray = NULL;
  656. }
  657. /** Remove and return the element in the SWheap with largest (worst) evalue
  658.  * @param self heap that contains record to be removed [in]
  659.  * @return record that was removed
  660.  */
  661. static SWResults *
  662. SWheapPop(SWheap * self)
  663. {
  664.   SWResults *results = NULL;
  665.   ConvertToHeap(self);
  666.   if(self->n > 0) { /* The heap is not empty */
  667.     SWheapRecord *first, *last; /* The first and last elements of the
  668.                                  * array that represents the heap. */
  669.     first = &self->heapArray[1];
  670.     last  = &self->heapArray[self->n];
  671.     results = first->theseAlignments;
  672.     
  673.     first->theseAlignments = last->theseAlignments;
  674.     first->bestEvalue      = last->bestEvalue;
  675.     SWheapifyDown(self->heapArray, 1, --self->n);
  676.   }
  677.   
  678.   KAPPA_ASSERT(SWheapIsValid(self->heapArray, 1, self->n));
  679.   return results;
  680. }
  681. /** Convert a SWheap to a flat list of SWResults. Note that there
  682.  * may be more than one alignment per match.  The list of all
  683.  * alignments are sorted by the following keys:
  684.  * - First by the evalue the best alignment between the query and a
  685.  *   particular matching sequence;
  686.  * - Second by the subject_index of the matching sequence; and
  687.  * - Third by the evalue of each individual alignment.
  688.  * @param self heap to be "flattened" [in]
  689.  * @return "flattened" version of the input 
  690.  */
  691. static SWResults *
  692. SWheapToFlatList(SWheap * self)
  693. {
  694.   SWResults *list = NULL;       /* the new list of SWResults */
  695.   SWResults *result;            /* the next list of alignments to be
  696.                                    prepended to "list" */
  697.   while(NULL != (result = SWheapPop(self))) {
  698.     SWResults *head, *remaining;     /* The head and remaining
  699.                                         elements in a list of
  700.                                         alignments to be prepended to
  701.                                         "list" */
  702.     remaining = result;
  703.     while(NULL != (head = remaining)) {
  704.       remaining   = head->next;
  705.       head->next  = list;
  706.       list        = head;
  707.     }
  708.   }
  709.   return list;
  710. }
  711. /** keeps one row of the Smith-Waterman matrix
  712.  */
  713. typedef struct SWpairs {
  714.   Int4 noGap;
  715.   Int4 gapExists;
  716. } SWpairs;
  717. /** computes Smith-Waterman local alignment score and returns the
  718.  * evalue
  719.  *
  720.  * @param matchSeq is a database sequence matched by this query [in]
  721.  * @param matchSeqLength is the length of matchSeq in amino acids [in]
  722.  * @param query is the input query sequence [in]
  723.  * @param queryLength is the length of query [in]
  724.  * @param matrix is the position-specific matrix associated with query [in]
  725.  * @param gapOpen is the cost of opening a gap [in]
  726.  * @param gapExtend is the cost of extending an existing gap by 1 position [in]
  727.  * @param matchSeqEnd returns the final position in the matchSeq of an optimal
  728.  *  local alignment [in]
  729.  * @param queryEnd returns the final position in query of an optimal
  730.  *  local alignment [in]
  731.  * matchSeqEnd and queryEnd can be used to run the local alignment in reverse
  732.  *  to find optimal starting positions [in]
  733.  * @param score is used to pass back the optimal score [in]
  734.  * @param kbp holds the Karlin-Altschul parameters [in]
  735.  * @param effSearchSpace effective search space for calculation of expect value [in]
  736.  * @param positionSpecific determines whether matrix is position specific or not [in]
  737.  * @return the expect value of the alignment
  738. */
  739. static double BLbasicSmithWatermanScoreOnly(Uint1 * matchSeq, 
  740.    Int4 matchSeqLength, Uint1 *query, Int4 queryLength, Int4 **matrix, 
  741.    Int4 gapOpen, Int4 gapExtend,  Int4 *matchSeqEnd, Int4 *queryEnd, Int4 *score,
  742.    Blast_KarlinBlk* kbp, Int8 effSearchSpace, Boolean positionSpecific)
  743. {
  744.    Int4 bestScore; /*best score seen so far*/
  745.    Int4 newScore;  /* score of next entry*/
  746.    Int4 bestMatchSeqPos, bestQueryPos; /*position ending best score in
  747.                            matchSeq and query sequences*/
  748.    SWpairs *scoreVector; /*keeps one row of the Smith-Waterman matrix
  749.                            overwrite old row with new row*/
  750.    Int4 *matrixRow; /*one row of score matrix*/
  751.    Int4 newGapCost; /*cost to have a gap of one character*/
  752.    Int4 prevScoreNoGapMatchSeq; /*score one row and column up
  753.                                with no gaps*/
  754.    Int4 prevScoreGapMatchSeq;   /*score if a gap already started in matchSeq*/
  755.    Int4 continueGapScore; /*score for continuing a gap in matchSeq*/
  756.    Int4 matchSeqPos, queryPos; /*positions in matchSeq and query*/
  757.    double returnEvalue; /*e-value to return*/
  758.    scoreVector = (SWpairs *) calloc(1, matchSeqLength * sizeof(SWpairs));
  759.    bestMatchSeqPos = 0;
  760.    bestQueryPos = 0;
  761.    bestScore = 0;
  762.    newGapCost = gapOpen + gapExtend;
  763.    for (matchSeqPos = 0; matchSeqPos < matchSeqLength; matchSeqPos++) {
  764.      scoreVector[matchSeqPos].noGap = 0;
  765.      scoreVector[matchSeqPos].gapExists = -(gapOpen);
  766.    }
  767.    for(queryPos = 0; queryPos < queryLength; queryPos++) {  
  768.      if (positionSpecific)
  769.        matrixRow = matrix[queryPos];
  770.      else
  771.        matrixRow = matrix[query[queryPos]];
  772.      newScore = 0;
  773.      prevScoreNoGapMatchSeq = 0;
  774.      prevScoreGapMatchSeq = -(gapOpen);
  775.      for(matchSeqPos = 0; matchSeqPos < matchSeqLength; matchSeqPos++) {
  776.        /*testing scores with a gap in matchSeq, either starting a new
  777.          gap or extending an existing gap*/
  778.        if ((newScore = newScore - newGapCost) > 
  779.    (prevScoreGapMatchSeq = prevScoreGapMatchSeq - gapExtend))
  780.          prevScoreGapMatchSeq = newScore;
  781.        /*testing scores with a gap in query, either starting a new
  782.          gap or extending an existing gap*/
  783.        if ((newScore = scoreVector[matchSeqPos].noGap - newGapCost) >
  784.            (continueGapScore = scoreVector[matchSeqPos].gapExists - gapExtend))
  785.          continueGapScore = newScore;
  786.        /*compute new score extending one position in matchSeq and query*/
  787.        newScore = prevScoreNoGapMatchSeq + matrixRow[matchSeq[matchSeqPos]];
  788.        if (newScore < 0)
  789.        newScore = 0; /*Smith-Waterman locality condition*/
  790.        /*test two alternatives*/
  791.        if (newScore < prevScoreGapMatchSeq)
  792.          newScore = prevScoreGapMatchSeq;
  793.        if (newScore < continueGapScore)
  794.          newScore = continueGapScore;
  795.        prevScoreNoGapMatchSeq = scoreVector[matchSeqPos].noGap; 
  796.        scoreVector[matchSeqPos].noGap = newScore;
  797.        scoreVector[matchSeqPos].gapExists = continueGapScore;
  798.        if (newScore > bestScore) {
  799.          bestScore = newScore;
  800.          bestQueryPos = queryPos;
  801.          bestMatchSeqPos = matchSeqPos;
  802.        }
  803.      }
  804.    }
  805.    sfree(scoreVector);
  806.    if (bestScore < 0)
  807.      bestScore = 0;
  808.    *matchSeqEnd = bestMatchSeqPos;
  809.    *queryEnd = bestQueryPos;
  810.    *score = bestScore;
  811.    returnEvalue = BLAST_KarlinStoE_simple(bestScore,kbp, effSearchSpace);
  812.    return(returnEvalue);
  813. }
  814. /** computes where optimal Smith-Waterman local alignment starts given the
  815.  *  ending positions and score
  816.  *  matchSeqEnd and queryEnd can be used to run the local alignment in reverse
  817.  *  to find optimal starting positions
  818.  *  these are passed back in matchSeqStart and queryStart
  819.  *  the optimal score is passed in to check when it has
  820.  *  been reached going backwards
  821.  * the score is also returned
  822.  * @param matchSeq is a database sequence matched by this query [in]
  823.  * @param matchSeqLength is the length of matchSeq in amino acids [in]
  824.  * @param query is the input query sequence  [in]
  825.  * @param matrix is the position-specific matrix associated with query
  826.  *      or the standard matrix [in]
  827.  * @param gapOpen is the cost of opening a gap [in]
  828.  * @param gapExtend is the cost of extending an existing gap by 1 position [in]
  829.  * @param matchSeqEnd is the final position in the matchSeq of an optimal
  830.  *      local alignment [in]
  831.  * @param queryEnd is the final position in query of an optimal
  832.  *  local alignment [in]
  833.  * @param score optimal score to be obtained [in]
  834.  * @param matchSeqStart starting point of optimal alignment [out]
  835.  * @param queryStart starting point of optimal alignment [out]
  836.  * @param positionSpecific determines whether matrix is position specific or not
  837. */
  838.   
  839. static Int4 BLSmithWatermanFindStart(Uint1 * matchSeq, 
  840.    Int4 matchSeqLength, Uint1 *query, Int4 **matrix, 
  841.    Int4 gapOpen, Int4 gapExtend,  Int4 matchSeqEnd, Int4 queryEnd, Int4 score,
  842.    Int4 *matchSeqStart, Int4 *queryStart, Boolean positionSpecific)
  843. {
  844.    Int4 bestScore; /*best score seen so far*/
  845.    Int4 newScore;  /* score of next entry*/
  846.    Int4 bestMatchSeqPos, bestQueryPos; /*position starting best score in
  847.                            matchSeq and database sequences*/
  848.    SWpairs *scoreVector; /*keeps one row of the Smith-Waterman matrix
  849.                            overwrite old row with new row*/
  850.    Int4 *matrixRow; /*one row of score matrix*/
  851.    Int4 newGapCost; /*cost to have a gap of one character*/
  852.    Int4 prevScoreNoGapMatchSeq; /*score one row and column up
  853.                                with no gaps*/
  854.    Int4 prevScoreGapMatchSeq;   /*score if a gap already started in matchSeq*/
  855.    Int4 continueGapScore; /*score for continuing a gap in query*/
  856.    Int4 matchSeqPos, queryPos; /*positions in matchSeq and query*/
  857.    scoreVector = (SWpairs *) calloc(1, matchSeqLength * sizeof(SWpairs));
  858.    bestMatchSeqPos = 0;
  859.    bestQueryPos = 0;
  860.    bestScore = 0;
  861.    newGapCost = gapOpen + gapExtend;
  862.    for (matchSeqPos = 0; matchSeqPos < matchSeqLength; matchSeqPos++) {
  863.      scoreVector[matchSeqPos].noGap = 0;
  864.      scoreVector[matchSeqPos].gapExists = -(gapOpen);
  865.    }
  866.    for(queryPos = queryEnd; queryPos >= 0; queryPos--) {  
  867.      if (positionSpecific)
  868.        matrixRow = matrix[queryPos];
  869.      else
  870.        matrixRow = matrix[query[queryPos]];
  871.      newScore = 0;
  872.      prevScoreNoGapMatchSeq = 0;
  873.      prevScoreGapMatchSeq = -(gapOpen);
  874.      for(matchSeqPos = matchSeqEnd; matchSeqPos >= 0; matchSeqPos--) {
  875.        /*testing scores with a gap in matchSeq, either starting a new
  876.          gap or extending an existing gap*/
  877.        if ((newScore = newScore - newGapCost) > 
  878.    (prevScoreGapMatchSeq = prevScoreGapMatchSeq - gapExtend))
  879.          prevScoreGapMatchSeq = newScore;
  880.        /*testing scores with a gap in query, either starting a new
  881.          gap or extending an existing gap*/
  882.        if ((newScore = scoreVector[matchSeqPos].noGap - newGapCost) >
  883.            (continueGapScore = scoreVector[matchSeqPos].gapExists - gapExtend))
  884.          continueGapScore = newScore;
  885.        /*compute new score extending one position in matchSeq and query*/
  886.        newScore = prevScoreNoGapMatchSeq + matrixRow[matchSeq[matchSeqPos]];
  887.        if (newScore < 0)
  888.        newScore = 0; /*Smith-Waterman locality condition*/
  889.        /*test two alternatives*/
  890.        if (newScore < prevScoreGapMatchSeq)
  891.          newScore = prevScoreGapMatchSeq;
  892.        if (newScore < continueGapScore)
  893.          newScore = continueGapScore;
  894.        prevScoreNoGapMatchSeq = scoreVector[matchSeqPos].noGap; 
  895.        scoreVector[matchSeqPos].noGap = newScore;
  896.        scoreVector[matchSeqPos].gapExists = continueGapScore;
  897.        if (newScore > bestScore) {
  898.          bestScore = newScore;
  899.          bestQueryPos = queryPos;
  900.          bestMatchSeqPos = matchSeqPos;
  901.        }
  902.        if (bestScore >= score)
  903.          break;
  904.      }
  905.      if (bestScore >= score)
  906.        break;
  907.    }
  908.    sfree(scoreVector);
  909.    if (bestScore < 0)
  910.      bestScore = 0;
  911.    *matchSeqStart = bestMatchSeqPos;
  912.    *queryStart = bestQueryPos;
  913.    return(bestScore);
  914. }
  915. /** computes Smith-Waterman local alignment score and returns the
  916.  *  evalue assuming some positions are forbidden
  917.  *  matchSeqEnd and query can be used to run the local alignment in reverse
  918.  *  to find optimal starting positions
  919.  * @param matchSeq is the matchSeq sequence [in]
  920.  * @param matchSeqLength is the length of matchSeq in amino acids [in]
  921.  * @param query is the input query sequence  [in]
  922.  * @param queryLength is the length of query [in]
  923.  * @param matrix is either the position-specific matrix associated with query
  924.  *     or the standard matrix [in]
  925.  * @param gapOpen is the cost of opening a gap [in]
  926.  * @param gapExtend is the cost of extending an existing gap by 1 position [in]
  927.  * @param matchSeqEnd returns the final position in the matchSeq of an optimal
  928.  *     local alignment [in]
  929.  * @param queryEnd returns the final position in query of an optimal
  930.  *     local alignment [in]
  931.  * @param score is used to pass back the optimal score [out]
  932.  * @param kbp holds the Karlin-Altschul parameters  [in]
  933.  * @param effSearchSpace effective search space [in]
  934.  * @param numForbidden number of forbidden ranges [in]
  935.  * @param forbiddenRanges lists areas that should not be aligned [in]
  936.  * @param positionSpecific determines whether matrix is position specific or not [in]
  937. */
  938. static double BLspecialSmithWatermanScoreOnly(Uint1 * matchSeq, 
  939.    Int4 matchSeqLength, Uint1 *query, Int4 queryLength, Int4 **matrix, 
  940.    Int4 gapOpen, Int4 gapExtend,  Int4 *matchSeqEnd, Int4 *queryEnd, Int4 *score,
  941.    Blast_KarlinBlk* kbp,  Int8 effSearchSpace,
  942.    Int4 *numForbidden, Int4 ** forbiddenRanges, Boolean positionSpecific)
  943. {
  944.    Int4 bestScore; /*best score seen so far*/
  945.    Int4 newScore;  /* score of next entry*/
  946.    Int4 bestMatchSeqPos, bestQueryPos; /*position ending best score in
  947.                            matchSeq and database sequences*/
  948.    SWpairs *scoreVector; /*keeps one row of the Smith-Waterman matrix
  949.                            overwrite old row with new row*/
  950.    Int4 *matrixRow; /*one row of score matrix*/
  951.    Int4 newGapCost; /*cost to have a gap of one character*/
  952.    Int4 prevScoreNoGapMatchSeq; /*score one row and column up
  953.                                with no gaps*/
  954.    Int4 prevScoreGapMatchSeq;   /*score if a gap already started in matchSeq*/
  955.    Int4 continueGapScore; /*score for continuing a gap in query*/
  956.    Int4 matchSeqPos, queryPos; /*positions in matchSeq and query*/
  957.    double returnEvalue; /*e-value to return*/
  958.    Boolean forbidden; /*is this position forbidden?*/
  959.    Int4 f; /*index over forbidden positions*/
  960.    scoreVector = (SWpairs *) calloc(1, matchSeqLength * sizeof(SWpairs));
  961.    bestMatchSeqPos = 0;
  962.    bestQueryPos = 0;
  963.    bestScore = 0;
  964.    newGapCost = gapOpen + gapExtend;
  965.    for (matchSeqPos = 0; matchSeqPos < matchSeqLength; matchSeqPos++) {
  966.      scoreVector[matchSeqPos].noGap = 0;
  967.      scoreVector[matchSeqPos].gapExists = -(gapOpen);
  968.    }
  969.    for(queryPos = 0; queryPos < queryLength; queryPos++) {  
  970.      if (positionSpecific)
  971.        matrixRow = matrix[queryPos];
  972.      else
  973.        matrixRow = matrix[query[queryPos]];
  974.      newScore = 0;
  975.      prevScoreNoGapMatchSeq = 0;
  976.      prevScoreGapMatchSeq = -(gapOpen);
  977.      for(matchSeqPos = 0; matchSeqPos < matchSeqLength; matchSeqPos++) {
  978.        /*testing scores with a gap in matchSeq, either starting a new
  979.          gap or extending an existing gap*/
  980.        if ((newScore = newScore - newGapCost) > 
  981.    (prevScoreGapMatchSeq = prevScoreGapMatchSeq - gapExtend))
  982.          prevScoreGapMatchSeq = newScore;
  983.        /*testing scores with a gap in query, either starting a new
  984.          gap or extending an existing gap*/
  985.        if ((newScore = scoreVector[matchSeqPos].noGap - newGapCost) >
  986.            (continueGapScore = scoreVector[matchSeqPos].gapExists - gapExtend))
  987.          continueGapScore = newScore;
  988.        /*compute new score extending one position in matchSeq and query*/
  989.        forbidden = FALSE;
  990.        for(f = 0; f < numForbidden[queryPos]; f++) {
  991.          if ((matchSeqPos >= forbiddenRanges[queryPos][2 * f]) &&
  992.      (matchSeqPos <= forbiddenRanges[queryPos][2*f + 1])) {
  993.    forbidden = TRUE;
  994.    break;
  995.  }
  996.        }
  997.        if (forbidden)
  998.          newScore = BLAST_SCORE_MIN;
  999.        else
  1000.  newScore = prevScoreNoGapMatchSeq + matrixRow[matchSeq[matchSeqPos]];
  1001.        if (newScore < 0)
  1002.  newScore = 0; /*Smith-Waterman locality condition*/
  1003.        /*test two alternatives*/
  1004.        if (newScore < prevScoreGapMatchSeq)
  1005.  newScore = prevScoreGapMatchSeq;
  1006.        if (newScore < continueGapScore)
  1007.  newScore = continueGapScore;
  1008.        prevScoreNoGapMatchSeq = scoreVector[matchSeqPos].noGap; 
  1009.        scoreVector[matchSeqPos].noGap = newScore;
  1010.        scoreVector[matchSeqPos].gapExists = continueGapScore;
  1011.        if (newScore > bestScore) {
  1012.  bestScore = newScore;
  1013.  bestQueryPos = queryPos;
  1014.  bestMatchSeqPos = matchSeqPos;
  1015.        }
  1016.      }
  1017.    }
  1018.    sfree(scoreVector);
  1019.    if (bestScore < 0)
  1020.      bestScore = 0;
  1021.    *matchSeqEnd = bestMatchSeqPos;
  1022.    *queryEnd = bestQueryPos;
  1023.    *score = bestScore;
  1024.    returnEvalue = BLAST_KarlinStoE_simple(bestScore,kbp, effSearchSpace);
  1025.    return(returnEvalue);
  1026. }
  1027. /** computes where optimal Smith-Waterman local alignment starts given the
  1028.  *  ending positions.   matchSeqEnd and queryEnd can be used to run the local alignment in reverse
  1029.  *  to find optimal starting positions
  1030.  * these are passed back in matchSeqStart and queryStart
  1031.  * the optimal score is passed in to check when it has
  1032.  *  been reached going backwards the score is also returned
  1033.  * @param matchSeq is the matchSeq sequence [in]
  1034.  * @param matchSeqLength is the length of matchSeq in amino acids [in]
  1035.  * @param query is the sequence corresponding to some matrix profile [in]
  1036.  * @param matrix is the position-specific matrix associated with query [in]
  1037.  * @param gapOpen is the cost of opening a gap [in]
  1038.  * @param gapExtend is the cost of extending an existing gap by 1 position [in]
  1039.  * @param matchSeqEnd is the final position in the matchSeq of an optimal
  1040.  *  local alignment [in]
  1041.  * @param queryEnd is the final position in query of an optimal
  1042.  *  local alignment [in]
  1043.  * @param score optimal score is passed in to check when it has
  1044.  *  been reached going backwards [in]
  1045.  * @param matchSeqStart optimal starting point [in]
  1046.  * @param queryStart optimal starting point [in]
  1047.  * @param numForbidden array of regions not to be aligned. [in]
  1048.  * @param numForbidden array of regions not to be aligned. [in]
  1049.  * @param forbiddenRanges regions not to be aligned. [in]
  1050.  * @param positionSpecific determines whether matrix is position specific or not
  1051.  * @return the score found
  1052. */
  1053. static Int4 BLspecialSmithWatermanFindStart(Uint1 * matchSeq, 
  1054.    Int4 matchSeqLength, Uint1 *query, Int4 **matrix, 
  1055.    Int4 gapOpen, Int4 gapExtend,  Int4 matchSeqEnd, Int4 queryEnd, Int4 score,
  1056.    Int4 *matchSeqStart, Int4 *queryStart, Int4 *numForbidden, 
  1057.    Int4 ** forbiddenRanges, Boolean positionSpecific)
  1058. {
  1059.    Int4 bestScore; /*best score seen so far*/
  1060.    Int4 newScore;  /* score of next entry*/
  1061.    Int4 bestMatchSeqPos, bestQueryPos; /*position starting best score in
  1062.                            matchSeq and database sequences*/
  1063.    SWpairs *scoreVector; /*keeps one row of the Smith-Waterman matrix
  1064.                            overwrite old row with new row*/
  1065.    Int4 *matrixRow; /*one row of score matrix*/
  1066.    Int4 newGapCost; /*cost to have a gap of one character*/
  1067.    Int4 prevScoreNoGapMatchSeq; /*score one row and column up
  1068.                                with no gaps*/
  1069.    Int4 prevScoreGapMatchSeq;   /*score if a gap already started in matchSeq*/
  1070.    Int4 continueGapScore; /*score for continuing a gap in query*/
  1071.    Int4 matchSeqPos, queryPos; /*positions in matchSeq and query*/
  1072.    Boolean forbidden; /*is this position forbidden?*/
  1073.    Int4 f; /*index over forbidden positions*/
  1074.    scoreVector = (SWpairs *) calloc(1, matchSeqLength * sizeof(SWpairs));
  1075.    bestMatchSeqPos = 0;
  1076.    bestQueryPos = 0;
  1077.    bestScore = 0;
  1078.    newGapCost = gapOpen + gapExtend;
  1079.    for (matchSeqPos = 0; matchSeqPos < matchSeqLength; matchSeqPos++) {
  1080.      scoreVector[matchSeqPos].noGap = 0;
  1081.      scoreVector[matchSeqPos].gapExists = -(gapOpen);
  1082.    }
  1083.    for(queryPos = queryEnd; queryPos >= 0; queryPos--) {  
  1084.      if (positionSpecific)
  1085.        matrixRow = matrix[queryPos];
  1086.      else
  1087.        matrixRow = matrix[query[queryPos]];
  1088.      newScore = 0;
  1089.      prevScoreNoGapMatchSeq = 0;
  1090.      prevScoreGapMatchSeq = -(gapOpen);
  1091.      for(matchSeqPos = matchSeqEnd; matchSeqPos >= 0; matchSeqPos--) {
  1092.        /*testing scores with a gap in matchSeq, either starting a new
  1093.          gap or extending an existing gap*/
  1094.        if ((newScore = newScore - newGapCost) > 
  1095.    (prevScoreGapMatchSeq = prevScoreGapMatchSeq - gapExtend))
  1096.          prevScoreGapMatchSeq = newScore;
  1097.        /*testing scores with a gap in query, either starting a new
  1098.          gap or extending an existing gap*/
  1099.        if ((newScore = scoreVector[matchSeqPos].noGap - newGapCost) >
  1100.            (continueGapScore = scoreVector[matchSeqPos].gapExists - gapExtend))
  1101.          continueGapScore = newScore;
  1102.        /*compute new score extending one position in matchSeq and query*/
  1103.        forbidden = FALSE;
  1104.        for(f = 0; f < numForbidden[queryPos]; f++) {
  1105.          if ((matchSeqPos >= forbiddenRanges[queryPos][2 * f]) &&
  1106.      (matchSeqPos <= forbiddenRanges[queryPos][2*f + 1])) {
  1107.    forbidden = TRUE;
  1108.    break;
  1109.  }
  1110.        }
  1111.        if (forbidden)
  1112.          newScore = BLAST_SCORE_MIN;
  1113.        else
  1114.  newScore = prevScoreNoGapMatchSeq + matrixRow[matchSeq[matchSeqPos]];
  1115.        if (newScore < 0)
  1116.        newScore = 0; /*Smith-Waterman locality condition*/
  1117.        /*test two alternatives*/
  1118.        if (newScore < prevScoreGapMatchSeq)
  1119.          newScore = prevScoreGapMatchSeq;
  1120.        if (newScore < continueGapScore)
  1121.          newScore = continueGapScore;
  1122.        prevScoreNoGapMatchSeq = scoreVector[matchSeqPos].noGap; 
  1123.        scoreVector[matchSeqPos].noGap = newScore;
  1124.        scoreVector[matchSeqPos].gapExists = continueGapScore;
  1125.        if (newScore > bestScore) {
  1126.          bestScore = newScore;
  1127.          bestQueryPos = queryPos;
  1128.          bestMatchSeqPos = matchSeqPos;
  1129.        }
  1130.        if (bestScore >= score)
  1131.          break;
  1132.      }
  1133.      if (bestScore >= score)
  1134.        break;
  1135.    }
  1136.    sfree(scoreVector);
  1137.    if (bestScore < 0)
  1138.      bestScore = 0;
  1139.    *matchSeqStart = bestMatchSeqPos;
  1140.    *queryStart = bestQueryPos;
  1141.    return(bestScore);
  1142. }
  1143. /** converts the list of Smith-Waterman alignments to a corresponding list
  1144.  * of HSP's. kbp stores parameters for computing the score
  1145.  * Code is adapted from procedure output_hits of pseed3.c
  1146.  * @param SWAligns List of Smith-Waterman alignments [in]
  1147.  * @param hitlist BlastHitList that is filled in [in|out]
  1148.  */
  1149. static Int2 newConvertSWalignsUpdateHitList(SWResults * SWAligns, BlastHitList* hitList)
  1150. {
  1151.     BlastHSPList* hspList=NULL;
  1152.     SWResults* curSW;
  1153.     
  1154.     if (SWAligns == NULL)
  1155.        return 0;
  1156.     curSW = SWAligns;
  1157.     while (curSW != NULL) {
  1158.         if (hspList == NULL)
  1159.         {
  1160.              hspList = Blast_HSPListNew(0); 
  1161.              hspList->oid = curSW->subject_index;
  1162.         }
  1163.         Blast_HSPListSaveHSP(hspList, curSW->hsp);
  1164.         curSW->hsp = NULL; /* Saved on the hitlist, will be deleted there. */
  1165.         /* Changing OID being worked on. */
  1166.         if (curSW->next == NULL ||
  1167.               curSW->subject_index != curSW->next->subject_index)
  1168.         {
  1169.              Blast_HitListUpdate(hitList, hspList);
  1170.              hspList = NULL;
  1171.         }
  1172.         curSW = curSW->next;
  1173.     }
  1174.     return 0;
  1175. }
  1176. /** allocates  a score matrix with numPositions positions and initializes some 
  1177.  * positions on the side
  1178.  * @param numPositions length of matrix (or query) [in]
  1179.  * @return matrix (Int4**)  
  1180.  */
  1181. static Int4 **allocateScaledMatrix(Int4 numPositions)
  1182. {
  1183.   Int4 **returnMatrix; /*allocated matrix to return*/
  1184.   Int4 c; /*loop index over characters*/
  1185.   returnMatrix = (Int4**) _PSIAllocateMatrix(numPositions+1, BLASTAA_SIZE, sizeof(Int4));
  1186.   for(c = 0; c < BLASTAA_SIZE; c++)
  1187.     returnMatrix[numPositions][c] = BLAST_SCORE_MIN;
  1188.   return(returnMatrix);
  1189. }
  1190. /** allocate a frequency ratio matrix with numPositions positions and initialize
  1191.  *  some positions.
  1192.  * @param numPositions the length of matrix or query [in]
  1193.  * @return frequency matrix (double**)
  1194.  */
  1195. static double **allocateStartFreqs(Int4 numPositions)
  1196. {
  1197.   double **returnMatrix; /*allocated matrix to return*/
  1198.   Int4 c; /*loop index over characters*/
  1199.   returnMatrix = (double**) _PSIAllocateMatrix(numPositions+1, BLASTAA_SIZE, sizeof(double));
  1200.   for(c = 0; c < BLASTAA_SIZE; c++)
  1201.     returnMatrix[numPositions][c] = BLAST_SCORE_MIN;
  1202.   return(returnMatrix);
  1203. }
  1204. #if 0 
  1205. FIXME delte if not needed
  1206. /*deallocate a frequency ratio matrix*/
  1207. static void freeStartFreqs(double **matrix, Int4 numPositions)
  1208. {
  1209.   int row; /*loop index*/
  1210.   for(row = 0; row <= numPositions; row++)
  1211.     sfree(matrix[row]);
  1212.   sfree(matrix);
  1213. }
  1214. #endif
  1215. /*matrix is a position-specific score matrix with matrixLength positions
  1216.   queryProbArray is an array containing the probability of occurrence
  1217.   of each residue in the query
  1218.   scoreArray is an array of probabilities for each score that is
  1219.     to be used as a field in return_sfp
  1220.   return_sfp is a the structure to be filled in and returned
  1221.   range is the size of scoreArray and is an upper bound on the
  1222.    difference between maximum score and minimum score in the matrix
  1223.   the routine posfillSfp computes the probability of each score weighted
  1224.    by the probability of each query residue and fills those probabilities
  1225.    into scoreArray and puts scoreArray as a field in
  1226.    that in the structure that is returned
  1227.    for indexing convenience the field storing scoreArray points to the
  1228.    entry for score 0, so that referring to the -k index corresponds to
  1229.    score -k */
  1230. static Blast_ScoreFreq* notposfillSfp(Int4 **matrix, double *subjectProbArray,  double *queryProbArray, double *scoreArray,  Blast_ScoreFreq* return_sfp, Int4 range)
  1231. {
  1232.   Int4 minScore, maxScore; /*observed minimum and maximum scores*/
  1233.   Int4 i,j,k; /* indices */
  1234.   minScore = maxScore = 0;
  1235.   for(i = 0; i < BLASTAA_SIZE; i++) {
  1236.     for(j = 0 ; j < PRO_TRUE_ALPHABET_SIZE; j++) {
  1237.       k = trueCharPositions[j];
  1238.       if ((matrix[i][k] != BLAST_SCORE_MIN) && (matrix[i][k] < minScore))
  1239. minScore = matrix[i][k];
  1240.       if (matrix[i][k] > maxScore)
  1241.         maxScore = matrix[i][k];
  1242.     }
  1243.   }
  1244.   return_sfp->obs_min = minScore;
  1245.   return_sfp->obs_max = maxScore;
  1246.   for (i = 0; i < range; i++)
  1247.     scoreArray[i] = 0.0;
  1248.   return_sfp->sprob = &(scoreArray[-minScore]); /*center around 0*/
  1249.   for(i = 0; i < BLASTAA_SIZE; i++) {
  1250.     for (j = 0; j < PRO_TRUE_ALPHABET_SIZE; j++) {
  1251.       k = trueCharPositions[j];
  1252.       if(matrix[i][k] >= minScore) {
  1253.         return_sfp->sprob[matrix[i][k]] += (queryProbArray[i] * subjectProbArray[k]);
  1254.       }
  1255.     }
  1256.   }
  1257.   return_sfp->score_avg = 0;
  1258.   for(i = minScore; i <= maxScore; i++)
  1259.     return_sfp->score_avg += i * return_sfp->sprob[i];
  1260.   return(return_sfp);
  1261. }
  1262. /*matrix is a position-specific score matrix with matrixLength positions
  1263.   subjectProbArray is an array containing the probability of occurrence
  1264.   of each residue in the matching sequence often called the subject
  1265.   scoreArray is an array of probabilities for each score that is
  1266.     to be used as a field in return_sfp
  1267.   return_sfp is a the structure to be filled in and returned
  1268.   range is the size of scoreArray and is an upper bound on the
  1269.    difference between maximum score and minimum score in the matrix
  1270.   the routine posfillSfp computes the probability of each score weighted
  1271.    by the probability of each query residue and fills those probabilities
  1272.    into scoreArray and puts scoreArray as a field in
  1273.    that in the structure that is returned
  1274.    for indexing convenience the field storing scoreArray points to the
  1275.    entry for score 0, so that referring to the -k index corresponds to
  1276.    score -k */
  1277. static Blast_ScoreFreq* posfillSfp(Int4 **matrix, Int4 matrixLength, double *subjectProbArray, double *scoreArray,  Blast_ScoreFreq* return_sfp, Int4 range)
  1278. {
  1279.   Int4 minScore, maxScore; /*observed minimum and maximum scores*/
  1280.   Int4 i,j,k; /* indices */
  1281.   double onePosFrac; /*1/matrix length as a double*/
  1282.   minScore = maxScore = 0;
  1283.   for(i = 0; i < matrixLength; i++) {
  1284.     for(j = 0 ; j < PRO_TRUE_ALPHABET_SIZE; j++) {
  1285.       k = trueCharPositions[j];
  1286.       if ((matrix[i][k] != BLAST_SCORE_MIN) && (matrix[i][k] < minScore))
  1287. minScore = matrix[i][k];
  1288.       if (matrix[i][k] > maxScore)
  1289.         maxScore = matrix[i][k];
  1290.     }
  1291.   }
  1292.   return_sfp->obs_min = minScore;
  1293.   return_sfp->obs_max = maxScore;
  1294.   for (i = 0; i < range; i++)
  1295.     scoreArray[i] = 0.0;
  1296.   return_sfp->sprob = &(scoreArray[-minScore]); /*center around 0*/
  1297.   onePosFrac = 1.0/ ((double) matrixLength);
  1298.   for(i = 0; i < matrixLength; i++) {
  1299.     for (j = 0; j < PRO_TRUE_ALPHABET_SIZE; j++) {
  1300.       k = trueCharPositions[j];
  1301.       if(matrix[i][k] >= minScore) {
  1302.         return_sfp->sprob[matrix[i][k]] += (onePosFrac * subjectProbArray[k]);
  1303.       }
  1304.     }
  1305.   }
  1306.   return_sfp->score_avg = 0;
  1307.   for(i = minScore; i <= maxScore; i++)
  1308.     return_sfp->score_avg += i * return_sfp->sprob[i];
  1309.   return(return_sfp);
  1310. }
  1311. /*Given a sequence of 'length' amino acid residues, compute the
  1312.   probability of each residue and put that in the array resProb*/
  1313. static void fillResidueProbability(Uint1* sequence, Int4 length, double * resProb)
  1314. {
  1315.   Int4 frequency[BLASTAA_SIZE]; /*frequency of each letter*/
  1316.   Int4 i; /*index*/
  1317.   Int4 localLength; /*reduce for X characters*/
  1318.   localLength = length;
  1319.   for(i = 0; i < BLASTAA_SIZE; i++)
  1320.     frequency[i] = 0;
  1321.   for(i = 0; i < length; i++) {
  1322.     if (XCHAR != sequence[i])
  1323.       frequency[sequence[i]]++;
  1324.     else
  1325.       localLength--;
  1326.   }
  1327.   for(i = 0; i < BLASTAA_SIZE; i++) {
  1328.     if (frequency[i] == 0)
  1329.       resProb[i] = 0.0;
  1330.     else
  1331.       resProb[i] = ((double) (frequency[i])) /((double) localLength);
  1332.   }
  1333. }
  1334. #define posEpsilon 0.0001
  1335. /** Return the a matrix of the frequency ratios that underlie the
  1336.  * score matrix being used on this pass. The returned matrix
  1337.  * is position-specific, so if we are in the first pass, use
  1338.  * query to convert the 20x20 standard matrix into a position-specific
  1339.  * variant. matrixName is the name of the underlying 20x20
  1340.  * score matrix used. numPositions is the length of the query;
  1341.  * startNumerator is the matrix of frequency ratios as stored
  1342.  * in posit.h. It needs to be divided by the frequency of the
  1343.  * second character to get the intended ratio 
  1344.  * @param sbp statistical information for blast [in]
  1345.  * @param query the query sequence [in]
  1346.  * @param matrixName name of the underlying matrix [in]
  1347.  * @param startNumerator matrix of frequency ratios as stored
  1348.  *      in posit.h. It needs to be divided by the frequency of the
  1349.  *      second character to get the intended ratio [in]
  1350.  * @param numPositions length of the query [in]
  1351.  */
  1352. static double **getStartFreqRatios(BlastScoreBlk* sbp,
  1353. Uint1* query,
  1354. const char *matrixName, 
  1355. double **startNumerator,
  1356. Int4 numPositions) 
  1357. {
  1358.    Blast_ResFreq* stdrfp; /* gets standard frequencies in prob field */
  1359.    double** returnRatios; /*frequency ratios to start investigating each pair*/
  1360.    double *standardProb; /*probabilities of each letter*/
  1361.    Int4 i,j;  /* Loop indices. */
  1362.    SFreqRatios* freqRatios=NULL; /* frequency ratio container for given matrix */
  1363.    returnRatios = allocateStartFreqs(numPositions);
  1364.    freqRatios = _PSIMatrixFrequencyRatiosNew(matrixName);
  1365.    ASSERT(freqRatios);
  1366.    if (freqRatios == NULL)
  1367. return NULL;
  1368.    for(i = 0; i < numPositions; i++) {
  1369.      for(j = 0; j < BLASTAA_SIZE; j++) {
  1370.    returnRatios[i][j] = freqRatios->data[query[i]][j];
  1371.      }
  1372.    }
  1373.    freqRatios = _PSIMatrixFrequencyRatiosFree(freqRatios);
  1374. /* FIXME use blast_psi_priv.c:_PSIGetStandardProbabilities when available here. */
  1375.    stdrfp = Blast_ResFreqNew(sbp);
  1376.    Blast_ResFreqStdComp(sbp,stdrfp); 
  1377.    standardProb = calloc(1, BLASTAA_SIZE * sizeof(double));
  1378.    for(i = 0; i < BLASTAA_SIZE; i++)
  1379.        standardProb[i] = stdrfp->prob[i];
  1380.      /*reverse multiplication done in posit.c*/
  1381.    for(i = 0; i < numPositions; i++) 
  1382.      for(j = 0; j < BLASTAA_SIZE; j++) 
  1383.        if ((standardProb[query[i]] > posEpsilon) && (standardProb[j] > posEpsilon) &&     
  1384.      (j != STARCHAR) && (j != XCHAR)
  1385.      && (startNumerator[i][j] > posEpsilon))
  1386.    returnRatios[i][j] = startNumerator[i][j]/standardProb[j];
  1387.    stdrfp = Blast_ResFreqDestruct(stdrfp);
  1388.    sfree(standardProb);
  1389.    return(returnRatios);
  1390. }
  1391. /** take every entry of startFreqRatios that is not corresponding to
  1392.  * a score of BLAST_SCORE_MIN and take its log, divide by Lambda and
  1393.  * multiply  by LambdaRatio then round to the nearest integer and
  1394.  * put the result in the corresponding entry of matrix.
  1395.  * startMatrix and matrix have dimensions numPositions X BLASTAA_SIZE
  1396.  * @param matrix preallocated matrix to be filled in [out]
  1397.  * @param startMatrix matrix to be scaled up [in]
  1398.  * @param startFreqRatios frequency ratios of starting matrix [in]
  1399.  * @param numPositions length of query [in]
  1400.  * @param Lambda A Karlin-Altschul parameter. [in]
  1401.  * @param LambdaRatio ratio of correct Lambda to it's original value [in]
  1402. */
  1403. static void scaleMatrix(Int4 **matrix, Int4 **startMatrix, 
  1404. double **startFreqRatios, Int4 numPositions, 
  1405. double Lambda, double LambdaRatio)
  1406. {
  1407.    Int4 p, c; /*indices over positions and characters*/
  1408.    double temp; /*intermediate term in computation*/
  1409.    for (p = 0; p < numPositions; p++) {
  1410.      for (c = 0; c < BLASTAA_SIZE; c++) {
  1411.        if (matrix[p][c] == BLAST_SCORE_MIN)
  1412.  matrix[p][c] = startMatrix[p][c];
  1413.        else {
  1414.          temp = log(startFreqRatios[p][c]);
  1415.          temp = temp/Lambda;
  1416.  temp = temp * LambdaRatio; 
  1417.  matrix[p][c] = BLAST_Nint(temp);
  1418.        }
  1419.      }
  1420.    }
  1421. }
  1422. /*SCALING_FACTOR is a multiplicative factor used to get more bits of
  1423.  * precision in the integer matrix scores. It cannot be arbitrarily
  1424.  * large because we do not want total alignment scores to exceedto
  1425.  * -(BLAST_SCORE_MIN) */
  1426. #define SCALING_FACTOR 32
  1427. /** Compute a scaled up version of the standard matrix encoded by matrix name. 
  1428.  * Standard matrices are in half-bit units.
  1429.  * @param matrix preallocated matrix [in][out]
  1430.  * @param matrixName name of matrix (e.g., BLOSUM62, PAM30). [in]
  1431.  * @param Lambda A Karlin-Altschul parameter. [in]
  1432. */
  1433. static void  computeScaledStandardMatrix(Int4 **matrix, char *matrixName, double Lambda)
  1434. {
  1435.    int i,j; /*loop indices*/
  1436.    double temp; /*intermediate term in computation*/
  1437.    SFreqRatios* freqRatios=NULL; /* frequency ratio container for given matrix */
  1438.    freqRatios = _PSIMatrixFrequencyRatiosNew(matrixName);
  1439.    ASSERT(freqRatios);
  1440.    if (freqRatios == NULL)
  1441. return;
  1442.    for(i = 0; i < BLASTAA_SIZE; i++)
  1443.      for(j = 0; j < BLASTAA_SIZE; j++) {
  1444.          if(0.0 == freqRatios->data[i][j])
  1445.    matrix[i][j] = BLAST_SCORE_MIN;
  1446.  else {
  1447.    temp = log(freqRatios->data[i][j])/Lambda;
  1448.            matrix[i][j] = BLAST_Nint(temp);
  1449.      }
  1450.    }
  1451.    freqRatios = _PSIMatrixFrequencyRatiosFree(freqRatios);
  1452.    return;
  1453. }
  1454. #if 0 /* FIXME */
  1455. /************************************************************
  1456. produce a scaled-up version of the position-specific matrix starting from
  1457. posFreqs
  1458. fillPosMatrix is the matrix to be filled
  1459. nonposMatrix is the underlying position-independent matrix, used to
  1460. fill positions where frequencies are irrelevant
  1461. sbp stores various parameters of the search
  1462. *****************************************************************/
  1463. void scalePosMatrix(Int4 **fillPosMatrix, Int4 **nonposMatrix, char *matrixName, double **posFreqs, Uint1 *query, Int4 queryLength, BLAST_ScoreBlk* sbp)
  1464. {
  1465.      posSearchItems *posSearch; /*used to pass data into scaling routines*/
  1466.      compactSearchItems *compactSearch; /*used to pass data into scaling routines*/
  1467.      Int4 i,j ; /*loop indices*/   
  1468.      BLAST_ResFreq* stdrfp; /* gets standard frequencies in prob field */
  1469.      Int4 a; /*index over characters*/
  1470.      double **standardFreqRatios; /*frequency ratios for standard score matrix*/
  1471.      Int4 multiplier; /*bit scale factor for scores*/
  1472.      posSearch = (posSearchItems *) calloc (1, sizeof(posSearchItems));
  1473.      compactSearch = (compactSearchItems *) calloc (1, sizeof(compactSearchItems));
  1474.      posSearch->posMatrix = (Int4 **) calloc((queryLength + 1), sizeof(Int4 *));
  1475.      posSearch->posPrivateMatrix = fillPosMatrix;
  1476.      posSearch->posFreqs = posFreqs;
  1477.      for(i = 0; i <= queryLength; i++) 
  1478.        posSearch->posMatrix[i] = (Int4 *) calloc(BLASTAA_SIZE, sizeof(Int4));
  1479.      compactSearch->query = (Uint1*) query;
  1480.      compactSearch->qlength = queryLength;
  1481.      compactSearch->alphabetSize = BLASTAA_SIZE;
  1482.      compactSearch->gapped_calculation = TRUE;
  1483.      compactSearch->matrix = nonposMatrix;
  1484.      compactSearch->lambda =  sbp->kbp_gap_std[0]->Lambda;
  1485.      compactSearch->kbp_std = sbp->kbp_std;
  1486.      compactSearch->kbp_psi = sbp->kbp_psi;
  1487.      compactSearch->kbp_gap_psi = sbp->kbp_gap_psi;
  1488.      compactSearch->kbp_gap_std = sbp->kbp_gap_std;
  1489.      compactSearch->lambda_ideal = sbp->kbp_ideal->Lambda;
  1490.      compactSearch->K_ideal = sbp->kbp_ideal->K;
  1491.      stdrfp = BlastResFreqNew(sbp);
  1492.      BlastResFreqStdComp(sbp,stdrfp); 
  1493.      compactSearch->standardProb = calloc(compactSearch->alphabetSize, sizeof(double));
  1494.      for(a = 0; a < compactSearch->alphabetSize; a++)
  1495.        compactSearch->standardProb[a] = stdrfp->prob[a];
  1496.      stdrfp = BlastResFreqDestruct(stdrfp);
  1497.      standardFreqRatios = (double **) calloc(BLASTAA_SIZE, sizeof(double *));
  1498.      for (i = 0; i < BLASTAA_SIZE; i++)
  1499.        standardFreqRatios[i] = (double *) calloc(BLASTAA_SIZE, sizeof(double));
  1500.      if ((0 == strcmp(matrixName,"BLOSUM62")) ||
  1501.  (0 == strcmp(matrixName,"BLOSUM62_20"))) {
  1502.        multiplier = 2;
  1503.        for(i = 0; i < BLASTAA_SIZE; i++)
  1504.  for(j = 0; j < BLASTAA_SIZE; j++)
  1505.    standardFreqRatios[i][j] = BLOSUM62_FREQRATIOS[i][j];
  1506.      }
  1507.      if (0 == strcmp(matrixName,"BLOSUM62_20A")) {
  1508.        multiplier = 2;
  1509.        for(i = 0; i < BLASTAA_SIZE; i++)
  1510.  for(j = 0; j < BLASTAA_SIZE; j++)
  1511.    standardFreqRatios[i][j] = 0.9666 * BLOSUM62_FREQRATIOS[i][j];
  1512.      }
  1513.      if (0 == strcmp(matrixName,"BLOSUM62_20B")) {
  1514.        multiplier = 2;
  1515.        for(i = 0; i < BLASTAA_SIZE; i++)
  1516.  for(j = 0; j < BLASTAA_SIZE; j++)
  1517.    standardFreqRatios[i][j] = 0.9344 * BLOSUM62_FREQRATIOS[i][j];
  1518.      }
  1519.      if (0 == strcmp(matrixName,"BLOSUM45")) {
  1520.        multiplier = 3;
  1521.        for(i = 0; i < BLASTAA_SIZE; i++)
  1522.  for(j = 0; j < BLASTAA_SIZE; j++)
  1523.    standardFreqRatios[i][j] = BLOSUM45_FREQRATIOS[i][j];
  1524.      }
  1525.      if (0 == strcmp(matrixName,"BLOSUM80")) {
  1526.        multiplier = 2;
  1527.        for(i = 0; i < BLASTAA_SIZE; i++)
  1528.  for(j = 0; j < BLASTAA_SIZE; j++)
  1529.    standardFreqRatios[i][j] = BLOSUM80_FREQRATIOS[i][j];
  1530.      }
  1531.      if (0 == strcmp(matrixName,"BLOSUM50")) {
  1532.        multiplier = 2;
  1533.        for(i = 0; i < BLASTAA_SIZE; i++)
  1534.  for(j = 0; j < BLASTAA_SIZE; j++)
  1535.    standardFreqRatios[i][j] = BLOSUM50_FREQRATIOS[i][j];
  1536.      }
  1537.      if (0 == strcmp(matrixName,"BLOSUM90")) {
  1538.        multiplier = 2;
  1539.        for(i = 0; i < PROTEIN_ALPHABET; i++)
  1540.  for(j = 0; j < PROTEIN_ALPHABET; j++)
  1541.    standardFreqRatios[i][j] = BLOSUM90_FREQRATIOS[i][j];
  1542.      }
  1543.      if (0 == strcmp(matrixName,"PAM250")) {
  1544.        multiplier = 2;
  1545.        for(i = 0; i < PROTEIN_ALPHABET; i++)
  1546.  for(j = 0; j < PROTEIN_ALPHABET; j++)
  1547.    standardFreqRatios[i][j] = PAM250_FREQRATIOS[i][j];
  1548.      }
  1549.      if (0 == strcmp(matrixName,"PAM30")) {
  1550.        multiplier = 2;
  1551.        for(i = 0; i < PROTEIN_ALPHABET; i++)
  1552.  for(j = 0; j < PROTEIN_ALPHABET; j++)
  1553.    standardFreqRatios[i][j] = PAM30_FREQRATIOS[i][j];
  1554.      }
  1555.      if (0 == strcmp(matrixName,"PAM70")) {
  1556.        multiplier = 2;
  1557.        for(i = 0; i < PROTEIN_ALPHABET; i++)
  1558.  for(j = 0; j < PROTEIN_ALPHABET; j++)
  1559.    standardFreqRatios[i][j] = PAM70_FREQRATIOS[i][j];
  1560.      }
  1561.      posFreqsToMatrix(posSearch,compactSearch, standardFreqRatios, multiplier);
  1562.      impalaScaling(posSearch, compactSearch, ((double) SCALING_FACTOR), FALSE);
  1563.      for(i = 0; i <= queryLength; i++)
  1564.        sfree(posSearch->posMatrix[i]);
  1565.      for(i = 0; i < PROTEIN_ALPHABET; i++)
  1566.        sfree(standardFreqRatios[i]);
  1567.      sfree(standardFreqRatios);
  1568.      sfree(compactSearch->standardProb);
  1569.      sfree(posSearch->posMatrix);
  1570.      sfree(posSearch);
  1571.      sfree(compactSearch);
  1572. }
  1573. #endif
  1574. /**
  1575.  * A Kappa_MatchingSequence represents a subject sequence to be aligned
  1576.  * with the query.  This abstract sequence is used to hide the
  1577.  * complexity associated with actually obtaining and releasing the
  1578.  * data for a matching sequence, e.g. reading the sequence from a DB
  1579.  * or translating it from a nucleotide sequence. 
  1580.  */
  1581. struct Kappa_MatchingSequence {
  1582.   Int4      length;             /**< length of the sequence */
  1583.   Uint1*  sequence;           /**< the sequence data */
  1584.   Uint1*  filteredSequence;   /**< a copy of the sequence data that has 
  1585.                                    been filtered */
  1586.   Uint1*  filteredSequenceStart;      /**< the address of the chunk of
  1587.                                            memory that has been
  1588.                                            allocated to hold
  1589.                                            "filterSequence". */
  1590.   BLAST_SequenceBlk* seq_blk;   /**< sequence blk for "database" sequence. */
  1591. };
  1592. typedef struct Kappa_MatchingSequence Kappa_MatchingSequence;
  1593. #define BLASTP_MASK_INSTRUCTIONS "S 10 1.8 2.1"
  1594. /** Initialize a new matching sequence, obtaining the data from an
  1595.  * appropriate location 
  1596.  * @param self the Kappa_MatchingSequence to be filled in [in|out]
  1597.  * @param seqSrc Used to access match sequences [in]
  1598.  * @param subject_id ordinal ID of matching sequence [in]
  1599.  */
  1600. static void
  1601. Kappa_MatchingSequenceInitialize(Kappa_MatchingSequence * self,
  1602.                                  const BlastSeqSrc* seqSrc,
  1603.                                  Int4 subject_id)
  1604. {
  1605.   GetSeqArg seq_arg;
  1606.   memset((void*) &seq_arg, 0, sizeof(seq_arg));
  1607.   seq_arg.oid = subject_id;
  1608.   seq_arg.encoding = BLASTP_ENCODING;
  1609.   BlastSequenceBlkClean(seq_arg.seq);
  1610.   if (BLASTSeqSrcGetSequence(seqSrc, (void*) &seq_arg) < 0)
  1611. return;
  1612.   self->length = BLASTSeqSrcGetSeqLen(seqSrc, &seq_arg);
  1613.   self->sequence = BlastMemDup(seq_arg.seq->sequence, (1+self->length)*sizeof(Uint1));
  1614.   self->filteredSequenceStart = calloc((self->length + 2), sizeof(Uint1));
  1615.   self->filteredSequence      = self->filteredSequenceStart + 1;
  1616.   memcpy(self->filteredSequence, self->sequence, self->length);
  1617. #ifndef KAPPA_NO_SEG_SEQUENCE
  1618. /*take as input an amino acid  string and its length; compute a filtered
  1619.   amino acid string and return the filtered string*/
  1620.   {{
  1621.      BlastSeqLoc* mask_seqloc;
  1622.      const Uint1 k_program_name = blast_type_blastp;
  1623.      BlastSetUp_Filter(k_program_name, self->sequence, self->length,
  1624.         0, BLASTP_MASK_INSTRUCTIONS, NULL, &mask_seqloc);
  1625.      Blast_MaskTheResidues(self->filteredSequence, self->length, FALSE, mask_seqloc, FALSE, 0);
  1626.      mask_seqloc = BlastSeqLocFree(mask_seqloc);
  1627.   }}
  1628. #endif
  1629.   self->seq_blk = NULL;
  1630.   BlastSetUp_SeqBlkNew(self->filteredSequence, self->length, 0, &(self->seq_blk), FALSE);
  1631.   return;
  1632. }
  1633. /** Release the data associated with a matching sequence
  1634.  * @param self the Kappa_MatchingSequence whose data will be freed [in|out]
  1635.  */
  1636. static void
  1637. Kappa_MatchingSequenceRelease(Kappa_MatchingSequence * self)
  1638. {
  1639.   if(self->sequence != self->filteredSequence) {
  1640.     sfree(self->filteredSequenceStart);
  1641.   }
  1642.   sfree(self->sequence);
  1643.   self->seq_blk = BlastSequenceBlkFree(self->seq_blk);
  1644. }
  1645. /** An instance of Kappa_ForbiddenRanges is used by the Smith-Waterman
  1646.  * algorithm to represent ranges in the database that are not to be
  1647.  * aligned.
  1648.  */
  1649. struct Kappa_ForbiddenRanges { 
  1650.   Int4 *numForbidden;           /**< how many forbidden ranges at each db  
  1651.                                   position */
  1652.   Int4 **ranges;                /**< forbidden ranges for each database
  1653.                                   position */
  1654.   Int4   queryLength;           /**< length of query. */
  1655. };
  1656. typedef struct Kappa_ForbiddenRanges Kappa_ForbiddenRanges;
  1657. /** Initialize a new, empty Kappa_ForbiddenRanges
  1658.  * @param self object to be initialized [in|out]
  1659.  * @param queryLength length of the query [in]
  1660.  */
  1661. static void
  1662. Kappa_ForbiddenRangesInitialize(
  1663.   Kappa_ForbiddenRanges * self, 
  1664.   Int4 queryLength              
  1665. ) {
  1666.   Int4 f;
  1667.   self->queryLength  = queryLength;
  1668.   self->numForbidden = (Int4 *) calloc(queryLength, sizeof(Int4));
  1669.   self->ranges       = (Int4 **) calloc(queryLength, sizeof(Int4 *));
  1670.   for(f = 0; f < queryLength; f++) {
  1671.     self->numForbidden[f] = 0;
  1672.     self->ranges[f]       = (Int4 *) calloc(2, sizeof(Int4));
  1673.     self->ranges[f][0]    = 0;
  1674.     self->ranges[f][1]    = 0;
  1675.   }
  1676. }
  1677. /** Reset self to be empty 
  1678.  * @param self the object to be reset [in|out]
  1679.  */
  1680. static void
  1681. Kappa_ForbiddenRangesClear(Kappa_ForbiddenRanges * self)
  1682. {
  1683.   Int4 f;
  1684.   for(f = 0; f < self->queryLength; f++) {
  1685.     self->numForbidden[f] = 0;
  1686.   }
  1687. }
  1688. /** Add some ranges to self 
  1689.  * @param self object to be be "pushed" [in|out]
  1690.  * @param queryStart start of the alignment in the query sequence [in]
  1691.  * @param queryAlignmentExtent length of the alignment in the query sequence [in]
  1692.  * @param matchStart start of the alignment in the subject sequence [in]
  1693.  * @param matchAlignmentExtent length of the alignment in the subject sequence  [in]
  1694.  */
  1695. static void
  1696. Kappa_ForbiddenRangesPush(
  1697.   Kappa_ForbiddenRanges * self,
  1698.   Int4 queryStart,      /* start of the alignment in the query sequence */
  1699.   Int4 queryAlignmentExtent,   /* length of the alignment in the query sequence */
  1700.   Int4 matchStart,      /* start of the alignment in the subject sequence */
  1701.   Int4 matchAlignmentExtent)   /* length of the alignment in the subject  sequence */
  1702. {
  1703.   Int4 f;
  1704.   for(f = queryStart; f < (queryStart + queryAlignmentExtent); f++) {
  1705.     Int4 last = 2 * self->numForbidden[f];
  1706.     if(0 != last) {    /* we must resize the array */
  1707.       self->ranges[f] =
  1708.         (Int4 *) realloc(self->ranges[f], (last + 2) * sizeof(Int4));
  1709.     }
  1710.     self->ranges[f][last]     = matchStart;
  1711.     self->ranges[f][last + 1] = matchStart + matchAlignmentExtent;
  1712.     self->numForbidden[f]++;
  1713.   }
  1714. }
  1715. /** Release the storage associated with the fields of self, but do not 
  1716.  * delete self 
  1717.  * @param self the object whose storage will be released [in|out]
  1718.  */
  1719. static void
  1720. Kappa_ForbiddenRangesRelease(Kappa_ForbiddenRanges * self)
  1721. {
  1722.   Int4 f;
  1723.   for(f = 0; f < self->queryLength; f++)  sfree(self->ranges[f]);
  1724.   
  1725.   sfree(self->ranges);       self->ranges       = NULL;
  1726.   sfree(self->numForbidden); self->numForbidden = NULL;
  1727. }
  1728. /** Redo a S-W alignment using an x-drop alignment.  The result will
  1729.  * usually be the same as the S-W alignment. The call to ALIGN
  1730.  * attempts to force the endpoints of the alignment to match the
  1731.  * optimal endpoints determined by the Smith-Waterman algorithm.
  1732.  * ALIGN is used, so that if the data structures for storing BLAST
  1733.  * alignments are changed, the code will not break 
  1734.  *
  1735.  * @param query the query sequence [in]
  1736.  * @param queryLength length of the query sequence [in]
  1737.  * @param queryStart start of the alignment in the query sequence [in]
  1738.  * @param queryEnd end of the alignment in the query sequence,
  1739.  *                          as computed by the Smith-Waterman algorithm [in]
  1740.  * @param match the subject (database) sequence [in]
  1741.  * @param matchLength length of the subject sequence [in]
  1742.  * @param matchStart start of the alignment in the subject sequence [in]
  1743.  * @param matchEnd end of the alignment in the query sequence,
  1744.                            as computed by the Smith-Waterman algorithm [in]
  1745.  * @param gap_align parameters for a gapped alignment [in]
  1746.  * @param scoringParams Settings for gapped alignment.[in]
  1747.  * @param score score computed by the Smith-Waterman algorithm [in]
  1748.  * @param localScalingFactor the factor by which the
  1749.  *                 scoring system has been scaled in order to obtain
  1750.  *                 greater precision [in]
  1751.  * @param * queryAlignmentExtent length of the alignment in the query sequence,
  1752.  *                          as computed by the x-drop algorithm [out]
  1753.  * @param * matchAlignmentExtent length of the alignment in the subject sequence,
  1754.  *                          as computed by the x-drop algorithm  [out]
  1755.  * @param ** reverseAlignScript alignment information (script) returned by 
  1756.                             a x-drop alignment algorithm [out]
  1757.  * @param * newScore alignment score computed by the x-drop algorithm [out]
  1758.  */
  1759. static void
  1760. Kappa_SWFindFinalEndsUsingXdrop(
  1761.   Uint1* query,       /* the query sequence */
  1762.   Int4 queryLength,     /* length of the query sequence */
  1763.   Int4 queryStart,      /* start of the alignment in the query sequence */
  1764.   Int4 queryEnd,        /* end of the alignment in the query sequence,
  1765.                            as computed by the Smith-Waterman algorithm */
  1766.   Uint1* match,       /* the subject (database) sequence */
  1767.   Int4 matchLength,     /* length of the subject sequence */
  1768.   Int4 matchStart,      /* start of the alignment in the subject sequence */
  1769.   Int4 matchEnd,        /* end of the alignment in the query sequence,
  1770.                            as computed by the Smith-Waterman algorithm */
  1771.   BlastGapAlignStruct* gap_align,     /* parameters for a gapped alignment */
  1772.   const BlastScoringParameters* scoringParams, /* Settings for gapped alignment. */
  1773.   Int4 score,           /* score computed by the Smith-Waterman algorithm */
  1774.   double localScalingFactor,       /* the factor by which the
  1775.                                          * scoring system has been
  1776.                                          * scaled in order to obtain
  1777.                                          * greater precision */
  1778.   Int4 * queryAlignmentExtent, /* length of the alignment in the query sequence,
  1779.                            as computed by the x-drop algorithm */
  1780.   Int4 * matchAlignmentExtent, /* length of the alignment in the subject sequence,
  1781.                            as computed by the x-drop algorithm */
  1782.   Int4 ** reverseAlignScript,   /* alignment information (script)
  1783.                                  * returned by a x-drop alignment algorithm */
  1784.   Int4 * newScore        /* alignment score computed by the
  1785.                                    x-drop algorithm */
  1786. ) {
  1787.   Int4 XdropAlignScore;         /* alignment score obtained using X-dropoff
  1788.                                  * method rather than Smith-Waterman */
  1789.   Int4 doublingCount = 0;       /* number of times X-dropoff had to be
  1790.                                  * doubled */
  1791.   do {
  1792.     Int4 *alignScript;          /* the alignment script that will be
  1793.                                    generated below by the ALIGN
  1794.                                    routine. */
  1795.     
  1796.     *reverseAlignScript = alignScript =
  1797.       (Int4 *) calloc(matchLength, (queryLength + 3) * sizeof(Int4));
  1798.     XdropAlignScore =
  1799.       ALIGN_EX(&(query[queryStart]) - 1, &(match[matchStart]) - 1,
  1800.             queryEnd - queryStart + 1, matchEnd - matchStart + 1,
  1801.             *reverseAlignScript, queryAlignmentExtent, matchAlignmentExtent, &alignScript,
  1802.             gap_align, scoringParams, queryStart - 1, FALSE, FALSE);
  1803.     gap_align->gap_x_dropoff *= 2;
  1804.     doublingCount++;
  1805.     if((XdropAlignScore < score) && (doublingCount < 3)) {
  1806.       sfree(*reverseAlignScript);
  1807.     }
  1808.   } while((XdropAlignScore < score) && (doublingCount < 3));
  1809.   *newScore = BLAST_Nint(((double) XdropAlignScore) / localScalingFactor);
  1810. }
  1811. /** A Kappa_SearchParameters represents the data needed by
  1812.  * RedoAlignmentCore to adjust the parameters of a search, including
  1813.  * the original value of these parameters 
  1814.  */
  1815. struct Kappa_SearchParameters {
  1816.   Int4          gapOpen;        /**< a penalty for the existence of a gap */
  1817.   Int4          gapExtend;      /**< a penalty for each residue (or nucleotide) 
  1818.                                  * in the gap */
  1819.   Int4          gapDecline;     /**< a penalty for declining to align a pair of 
  1820.                                  * residues */
  1821.   Int4          mRows, nCols;   /**< the number of rows an columns in a scoring 
  1822.                                  * matrix */
  1823.   double   scaledUngappedLambda;   /**< The value of Karlin-Altchul
  1824.                                          * parameter lambda, rescaled
  1825.                                          * to allow scores to have
  1826.                                          * greater precision */
  1827.   Int4 **startMatrix, **origMatrix;
  1828.   SFreqRatios* sFreqRatios;        /**< Stores the frequency ratios along 
  1829.                                          *  with their bit scale factor */
  1830.   double **startFreqRatios;        /**< frequency ratios to start
  1831.                                          * investigating each pair */
  1832.   double  *scoreArray;      /**< array of score probabilities */
  1833.   double  *resProb;         /**< array of probabilities for each residue in 
  1834.                                   * a matching sequence */
  1835.   double  *queryProb;       /**< array of probabilities for each residue in 
  1836.                                   * the query */
  1837.   Boolean       adjustParameters;
  1838.   Blast_ScoreFreq* return_sfp;        /**< score frequency pointers to
  1839.                                          * compute lambda */
  1840.   Blast_KarlinBlk *kbp_gap_orig, **orig_kbp_gap_array; /* FIXME, AS only had one * on orig_kbp_gap_array, check with him about this. */
  1841.   double scale_factor;      /**< The original scale factor (to be restored). */
  1842. };
  1843. typedef struct Kappa_SearchParameters Kappa_SearchParameters;
  1844. /** Release the date associated with a Kappa_SearchParameters and
  1845.  * delete the object 
  1846.  * @param searchParams the object to be deleted [in][out]
  1847. */
  1848. static void
  1849. Kappa_SearchParametersFree(Kappa_SearchParameters ** searchParams)
  1850. {
  1851.   /* for convenience, remove one level of indirection from searchParams */
  1852.   Kappa_SearchParameters *sp = *searchParams; 
  1853.   if(sp->kbp_gap_orig) Blast_KarlinBlkDestruct(sp->kbp_gap_orig);
  1854.   /* An extra row is added at end during allocation. */
  1855.   if(sp->startMatrix)     _PSIDeallocateMatrix((void**) sp->startMatrix, 1+sp->mRows);
  1856.   if(sp->origMatrix)      _PSIDeallocateMatrix((void**) sp->origMatrix, 1+sp->mRows);
  1857.   if(sp->sFreqRatios)     _PSIMatrixFrequencyRatiosFree(sp->sFreqRatios);
  1858. /*
  1859.   if(sp->startFreqRatios) freeStartFreqs(sp->startFreqRatios, sp->mRows);
  1860. */
  1861.   if(sp->return_sfp) sfree(sp->return_sfp);
  1862.   if(sp->scoreArray) sfree(sp->scoreArray);
  1863.   if(sp->resProb)    sfree(sp->resProb);
  1864.   if(sp->queryProb)  sfree(sp->queryProb);
  1865.   sfree(*searchParams);
  1866.   *searchParams = NULL;
  1867. }
  1868. /** Create a new instance of Kappa_SearchParameters 
  1869.  * @param number of rows in the scoring matrix [in]
  1870.  * @param adjustParameters if true, use composition-based statistics [in]
  1871.  * @param positionBased if true, the search is position-based [in]
  1872. */
  1873. static Kappa_SearchParameters *
  1874. Kappa_SearchParametersNew(
  1875.   Int4 rows,                    /* number of rows in the scoring matrix */
  1876.   Boolean adjustParameters,     /* if true, use composition-based statistics */
  1877.   Boolean positionBased         /* if true, the search is position-based */
  1878. ) {
  1879.   Kappa_SearchParameters *sp;   /* the new object */
  1880.   sp = malloc(sizeof(Kappa_SearchParameters));
  1881.   sp->orig_kbp_gap_array = NULL;
  1882.   
  1883.   sp->mRows = positionBased ? rows : BLASTAA_SIZE;
  1884.   sp->nCols = BLASTAA_SIZE;
  1885.     
  1886.   sp->kbp_gap_orig     = NULL;
  1887.   sp->startMatrix      = NULL;
  1888.   sp->origMatrix       = NULL;
  1889.   sp->sFreqRatios      = NULL;
  1890.   sp->startFreqRatios  = NULL;
  1891.   sp->return_sfp       = NULL;
  1892.   sp->scoreArray       = NULL;
  1893.   sp->resProb          = NULL;
  1894.   sp->queryProb        = NULL;
  1895.   sp->adjustParameters = adjustParameters;
  1896.   
  1897.   if(adjustParameters) {
  1898.     sp->kbp_gap_orig = Blast_KarlinBlkCreate();
  1899.     sp->startMatrix  = allocateScaledMatrix(sp->mRows);
  1900.     sp->origMatrix   = allocateScaledMatrix(sp->mRows);
  1901.     
  1902.     sp->resProb    =
  1903.       (double *) calloc(BLASTAA_SIZE, sizeof(double));
  1904.     sp->scoreArray =
  1905.       (double *) calloc(scoreRange, sizeof(double));
  1906.     sp->return_sfp =
  1907.       (Blast_ScoreFreq*) calloc(1, sizeof(Blast_ScoreFreq));
  1908.     
  1909.     if(!positionBased) {
  1910.       sp->queryProb =
  1911.         (double *) calloc(BLASTAA_SIZE, sizeof(double));
  1912.     }
  1913.   }
  1914.   /* end if(adjustParameters) */
  1915.   return sp;
  1916. }
  1917. /** Record the initial value of the search parameters that are to be
  1918.  * adjusted. 
  1919.  * @param searchParams the object to be filled in [in|out]
  1920.  * @param queryBlk query sequence [in]
  1921.  * @param queryInfo query sequence information [in]
  1922.  * @param sbp Scoring Blk (contains Karlin-Altschul parameters) [in]
  1923.  * @param scoring gap-open/extend/decline_align information [in]
  1924.  */
  1925. static void
  1926. Kappa_RecordInitialSearch(Kappa_SearchParameters * searchParams, 
  1927.                           BLAST_SequenceBlk * queryBlk,
  1928.                           BlastQueryInfo* queryInfo,
  1929.                           BlastScoreBlk* sbp,
  1930.                           const BlastScoringParameters* scoring)
  1931. {
  1932.   Uint1* query;               /* the query sequence */
  1933.   Int4 queryLength;             /* the length of the query sequence */
  1934.   const Int4 k_context_offset = queryInfo->context_offsets[0];  /* offset in buffer of start of query. */
  1935.   query = &queryBlk->sequence[k_context_offset];
  1936.   queryLength = BLAST_GetQueryLength(queryInfo, 0);
  1937.   if(searchParams->adjustParameters) {
  1938.     Int4 i, j;
  1939.     Blast_KarlinBlk* kbp;     /* statistical parameters used to evaluate a
  1940.                                  * query-subject pair */
  1941.     Int4 **matrix;       /* matrix used to score a local
  1942.                                    query-subject alignment */
  1943.     Boolean positionBased = FALSE; /* FIXME, how is this set in scoring options? */
  1944.     if(positionBased) {
  1945.       kbp    = sbp->kbp_gap_psi[0];
  1946.       matrix = sbp->posMatrix;
  1947.     } else {
  1948.       kbp    = sbp->kbp_gap_std[0];
  1949.       matrix = sbp->matrix;
  1950.       fillResidueProbability(query, queryLength, searchParams->queryProb);
  1951.     }
  1952.     searchParams->gapOpen    = scoring->gap_open;
  1953.     searchParams->gapExtend  = scoring->gap_extend;
  1954.     searchParams->gapDecline = scoring->decline_align;
  1955.     searchParams->scale_factor   = scoring->scale_factor;
  1956.     searchParams->orig_kbp_gap_array   = sbp->kbp_gap;
  1957.     searchParams->kbp_gap_orig->Lambda = kbp->Lambda;
  1958.     searchParams->kbp_gap_orig->K      = kbp->K;
  1959.     searchParams->kbp_gap_orig->logK   = kbp->logK;
  1960.     searchParams->kbp_gap_orig->H      = kbp->H;
  1961.     for(i = 0; i < searchParams->mRows; i++) {
  1962.       for(j = 0; j < BLASTAA_SIZE; j++) {
  1963.         searchParams->origMatrix[i][j] = matrix[i][j];
  1964.       }
  1965.     }
  1966.   }
  1967. }
  1968. /** Rescale the search parameters in the search object and options object to
  1969.  * obtain more precision.
  1970.  * @param sp record of parameters used and frequencies [in|out]
  1971.  * @param queryBlk query sequence [in]
  1972.  * @param queryInfo query sequence information [in]
  1973.  * @param sbp Scoring Blk (contains Karlin-Altschul parameters) [in]
  1974.  * @param scoring gap-open/extend/decline_align information [in]
  1975.  * @return scaling-factor to be used.
  1976.  */
  1977. static double
  1978. Kappa_RescaleSearch(Kappa_SearchParameters * sp,
  1979.                     BLAST_SequenceBlk* queryBlk,
  1980.                     BlastQueryInfo* queryInfo,
  1981.                     BlastScoreBlk* sbp,
  1982.                     BlastScoringParameters* scoringParams)
  1983. {
  1984.   double localScalingFactor;       /* the factor by which to
  1985.                                          * scale the scoring system in
  1986.                                          * order to obtain greater
  1987.                                          * precision */
  1988.   if(!sp->adjustParameters) {
  1989.     localScalingFactor = 1.0;
  1990.   } else {
  1991.     double initialUngappedLambda;  /* initial value of the
  1992.                                          * statistical parameter
  1993.                                          * lambda used to evaluate
  1994.                                          * ungapped alignments */
  1995.     Blast_KarlinBlk* kbp;     /* the statistical parameters used to
  1996.                                  * evaluate alignments of a
  1997.                                  * query-subject pair */
  1998.     Uint1* query;             /* the query sequence */
  1999.     Int4 queryLength;           /* the length of the query sequence */
  2000.     Boolean positionBased=FALSE; /* FIXME, how is this set with options?? */
  2001.     if((0 == strcmp(scoringParams->options->matrix, "BLOSUM62_20"))) {
  2002.       localScalingFactor = SCALING_FACTOR / 10;
  2003.     } else {
  2004.       localScalingFactor = SCALING_FACTOR;
  2005.     }
  2006.     scoringParams->scale_factor = localScalingFactor;
  2007.     scoringParams->gap_open   = BLAST_Nint(sp->gapOpen   * localScalingFactor);
  2008.     scoringParams->gap_extend = BLAST_Nint(sp->gapExtend * localScalingFactor);
  2009.     if(sp->gapDecline != INT2_MAX) {
  2010.       scoringParams->decline_align =
  2011.         BLAST_Nint(sp->gapDecline * localScalingFactor);
  2012.     }
  2013.     query = &queryBlk->sequence[0];
  2014.     queryLength = BLAST_GetQueryLength(queryInfo, 0);
  2015.     if(positionBased) {
  2016.       sp->startFreqRatios =
  2017.         getStartFreqRatios(sbp, query, scoringParams->options->matrix,
  2018.                            sbp->posFreqs, queryLength);
  2019. /* FIXME      scalePosMatrix(sp->startMatrix, sbp->matrix, scoringParams->options->matrix,
  2020.                      sbp->posFreqs, query, queryLength, sbp);
  2021. */
  2022.       initialUngappedLambda = sbp->kbp_psi[0]->Lambda;
  2023.     } else {
  2024. /*
  2025.       sp->startFreqRatios =
  2026.         getStartFreqRatios(sbp, query, scoringParams->options->matrix, NULL,
  2027.                            PROTEIN_ALPHABET, FALSE);
  2028. */
  2029.       sp->sFreqRatios = _PSIMatrixFrequencyRatiosNew(scoringParams->options->matrix);
  2030.       sp->startFreqRatios = sp->sFreqRatios->data;
  2031.       initialUngappedLambda = sbp->kbp_ideal->Lambda;
  2032.     }
  2033.     sp->scaledUngappedLambda = initialUngappedLambda / localScalingFactor;
  2034.     if(!positionBased) {
  2035.       computeScaledStandardMatrix(sp->startMatrix, scoringParams->options->matrix,
  2036.                                   sp->scaledUngappedLambda);
  2037.     }
  2038.     if(positionBased) {
  2039.       kbp = sbp->kbp_gap_psi[0];
  2040.     } else {
  2041.       kbp = sbp->kbp_gap_std[0];
  2042.     }
  2043.     kbp->Lambda /= localScalingFactor;
  2044.     kbp->logK = log(kbp->K);
  2045.   }
  2046.   return localScalingFactor;
  2047. }
  2048. /*LambdaRatioLowerBound is used when the expected score is too large
  2049.  * causing impalaKarlinLambdaNR to give a Lambda estimate that
  2050.  * is too small, or to fail entirely returning -1*/
  2051. #define LambdaRatioLowerBound 0.5
  2052. /** Adjust the search parameters
  2053.  * @param searchParams a record of the initial search parameters [in|out]
  2054.  * @param queryLength length of query sequence [in]
  2055.  * @param filteredSequence a filtered subject sequence [in] 
  2056.  * @param length length of the filtered sequence  [in]
  2057.  * @param matrix a scoring matrix to be adjusted [out]
  2058.  * @return scaling-factor to be used.
  2059.  */
  2060. static Int4
  2061. Kappa_AdjustSearch(
  2062.   Kappa_SearchParameters * sp,  /* a record of the initial search parameters */
  2063.   Int4 queryLength,             /* length of the query. */
  2064.   Uint1* filteredSequence,    /* a filtered subject sequence */
  2065.   Int4 length,                  /* length of the filtered sequence */
  2066.   Int4 ** matrix         /* a scoring matrix to be adjusted */
  2067. ) {   
  2068.   double LambdaRatio;      /* the ratio of the corrected lambda to the 
  2069.                                  * original lambda */
  2070.   if(!sp->adjustParameters) {
  2071.     LambdaRatio = 1.0;
  2072.   } else {
  2073.     /* do adjust the parameters */
  2074.     Blast_ScoreFreq* this_sfp; 
  2075.     double correctUngappedLambda;  /* new value of ungapped lambda */
  2076.     Boolean positionBased=FALSE; /* FIXME */
  2077.     /* compute and plug in new matrix here */
  2078.     fillResidueProbability(filteredSequence, length, sp->resProb);
  2079.     if(positionBased) {
  2080.       this_sfp =
  2081.         posfillSfp(sp->startMatrix, queryLength, sp->resProb, sp->scoreArray,
  2082.                    sp->return_sfp, scoreRange);
  2083.     } else {
  2084.       this_sfp =
  2085.         notposfillSfp(sp->startMatrix, sp->resProb, sp->queryProb,
  2086.                       sp->scoreArray, sp->return_sfp, scoreRange);
  2087.     }
  2088.     correctUngappedLambda =
  2089.       Blast_KarlinLambdaNR(this_sfp, sp->scaledUngappedLambda);
  2090.     /* impalaKarlinLambdaNR will return -1 in the case where the
  2091.      * expected score is >=0; however, because of the MAX statement 3
  2092.      * lines below, LambdaRatio should always be > 0; the succeeding
  2093.      * test is retained as a vestige, in case one wishes to remove the
  2094.      * MAX statement and allow LambdaRatio to take on the error value
  2095.      * -1 */
  2096.     LambdaRatio = correctUngappedLambda / sp->scaledUngappedLambda;
  2097.     LambdaRatio = MIN(1, LambdaRatio);
  2098.     LambdaRatio = MAX(LambdaRatio, LambdaRatioLowerBound);
  2099.     if(LambdaRatio > 0) {
  2100.       scaleMatrix(matrix, sp->startMatrix, sp->startFreqRatios, sp->mRows,
  2101.                   sp->scaledUngappedLambda, LambdaRatio);
  2102.     }
  2103.   }
  2104.   /* end else do adjust the parameters */
  2105.   return LambdaRatio > 0 ? 0 : 1;
  2106. }
  2107. /** Restore the parameters that were adjusted to their original values
  2108.  * @param searchParams a record of the original values [in]
  2109.  * @param sbp Karlin-Altschul parameters to be restored. [out]
  2110.  * @param matrix the scoring matrix to be restored [out]
  2111.  * @param scoring the scoring parameters to be restored [out]
  2112. */
  2113. static void
  2114. Kappa_RestoreSearch(
  2115.   Kappa_SearchParameters * searchParams, 
  2116.   BlastScoreBlk* sbp,
  2117.   Int4 ** matrix,        
  2118.   BlastScoringParameters* scoring
  2119. ) {
  2120.   if(searchParams->adjustParameters) {
  2121.     Blast_KarlinBlk* kbp;     /* statistical parameters used to
  2122.                                    evaluate the significance of
  2123.                                    alignment of a query-subject
  2124.                                    pair */
  2125.     Int4 i, j; /* loop variables. */
  2126.     Boolean positionBased=FALSE; /* FIXME. */
  2127.     scoring->gap_open = searchParams->gapOpen;
  2128.     scoring->gap_extend = searchParams->gapExtend;
  2129.     scoring->decline_align = searchParams->gapDecline;
  2130.     scoring->scale_factor = searchParams->scale_factor;
  2131.     sbp->kbp_gap       = searchParams->orig_kbp_gap_array;
  2132.     if(positionBased) {
  2133.       kbp = sbp->kbp_gap_psi[0];
  2134.     } else {
  2135.       kbp = sbp->kbp_gap_std[0];
  2136.     }
  2137.     kbp->Lambda = searchParams->kbp_gap_orig->Lambda;
  2138.     kbp->K      = searchParams->kbp_gap_orig->K;
  2139.     kbp->logK   = searchParams->kbp_gap_orig->logK;
  2140.     kbp->H      = searchParams->kbp_gap_orig->H;
  2141.     for(i = 0; i < searchParams->mRows; i++) {
  2142.       for(j = 0; j < BLASTAA_SIZE; j++) {
  2143.         matrix[i][j] = searchParams->origMatrix[i][j];
  2144.       }
  2145.     }
  2146.   }
  2147. }
  2148. /** Gets best expect value of the list
  2149.  *
  2150.  * @param hsplist the list to be examined [in]
  2151.  * @return the best (lowest) expect value found 
  2152.  */
  2153. static double
  2154. BlastHitsGetBestEvalue(BlastHSPList* hsplist)
  2155. {
  2156.     double retval = (double) INT4_MAX; /* return value */
  2157.     Int4 index; /* loop iterator */
  2158.     if (hsplist == NULL || hsplist->hspcnt == 0)
  2159.        return retval;
  2160.     for (index=0; index<hsplist->hspcnt; index++)
  2161.     {
  2162.          retval = MIN(retval, hsplist->hsp_array[index]->evalue);
  2163.     }
  2164.     return retval;
  2165. }
  2166. Int2
  2167. Kappa_RedoAlignmentCore(BLAST_SequenceBlk * queryBlk,
  2168.                   BlastQueryInfo* queryInfo,
  2169.                   BlastScoreBlk* sbp,
  2170.                   BlastHitList* hitList,
  2171.                   const BlastSeqSrc* seqSrc,
  2172.                   BlastScoringParameters* scoringParams,
  2173.                   const BlastExtensionParameters* extendParams,
  2174.                   const BlastHitSavingParameters* hitsavingParams,
  2175.                   const PSIBlastOptions* psiOptions)
  2176. {
  2177.   const Uint1 k_program_name = blast_type_blastp;
  2178.   Boolean adjustParameters = FALSE; /* If true take match composition into account
  2179.                                                           and seg match sequence. */
  2180.   Boolean SmithWaterman = FALSE; /* USe smith-waterman to get scores.*/
  2181.   Boolean positionBased=FALSE; /* FIXME, how is this determined? */
  2182.   Int2 status=0;              /* Return value. */
  2183.   Int4 index;                   /* index over matches */
  2184.   Uint1*    query;            /* the query sequence */
  2185.   Int4      queryLength;      /* the length of the query sequence */
  2186.   double localScalingFactor;       /* the factor by which to
  2187.                                          * scale the scoring system in
  2188.                                          * order to obtain greater
  2189.                                          * precision */
  2190.   Int4      **matrix;    /* score matrix */
  2191.   Blast_KarlinBlk* kbp;       /* stores Karlin-Altschul parameters */
  2192.   BlastGapAlignStruct*     gapAlign; /* keeps track of gapped alignment params */
  2193.   Kappa_SearchParameters *searchParams; /* the values of the search
  2194.                                          * parameters that will be
  2195.                                          * recorded, altered in the
  2196.                                          * search structure in this
  2197.                                          * routine, and then restored
  2198.                                          * before the routine
  2199.                                          * exits. */
  2200.   Kappa_ForbiddenRanges   forbidden;    /* forbidden ranges for each
  2201.                                          * database position (used in
  2202.                                          * Smith-Waterman alignments) */
  2203.   SWheap  significantMatches;  /* a collection of alignments of the
  2204.                                 * query sequence with sequences from
  2205.                                 * the database */
  2206.   BlastExtensionOptions* extendOptions=NULL; /* Options for extension. */
  2207.   BlastHitSavingOptions* hitsavingOptions=NULL; /* Options for saving hits. */
  2208.   /* Get pointer to options for extensions and hitsaving. */
  2209.   if (extendParams == NULL || (extendOptions=extendParams->options) == NULL)
  2210.        return -1;
  2211.   if (hitsavingParams == NULL || (hitsavingOptions=hitsavingParams->options) == NULL)
  2212.        return -1;
  2213.   if (extendParams->options->eTbackExt ==  eSmithWatermanTbck)
  2214.     SmithWaterman = TRUE;
  2215.   adjustParameters = extendParams->options->compositionBasedStats; 
  2216.   SWheapInitialize(&significantMatches, hitsavingOptions->hitlist_size,
  2217.                    hitsavingOptions->hitlist_size, psiOptions->inclusion_ethresh);
  2218.    sbp->kbp_ideal = Blast_KarlinBlkIdealCalc(sbp);
  2219.   /**** Validate parameters *************/
  2220.   if(0 == strcmp(scoringParams->options->matrix, "BLOSUM62_20") && !adjustParameters) {
  2221.     return 0;                   /* BLOSUM62_20 only makes sense if
  2222.                                  * adjustParameters is on */
  2223.   }
  2224.   /*****************/
  2225.   query = &queryBlk->sequence[0];
  2226.   queryLength = BLAST_GetQueryLength(queryInfo, 0);
  2227.   if(SmithWaterman) {
  2228.     Kappa_ForbiddenRangesInitialize(&forbidden, queryLength);
  2229.   }
  2230.   if ((status=BLAST_GapAlignStructNew(scoringParams, extendParams,
  2231.                     BLASTSeqSrcGetMaxSeqLen(seqSrc), queryLength, sbp,
  2232.                     &gapAlign)) != 0) 
  2233.       return status;
  2234.   if(positionBased) {
  2235.     kbp    = sbp->kbp_gap_psi[0];
  2236.     matrix = sbp->posMatrix;
  2237.     if(sbp->posFreqs == NULL) {
  2238.       sbp->posFreqs = (double**) _PSIAllocateMatrix(queryLength, BLASTAA_SIZE, sizeof(double));
  2239.     }
  2240.     } else {
  2241.     kbp    = sbp->kbp_gap_std[0];
  2242.     matrix = sbp->matrix;
  2243.   }
  2244.   /* Initialize searchParams */
  2245.   searchParams =
  2246.     Kappa_SearchParametersNew(queryLength, adjustParameters,
  2247.                               positionBased);
  2248.   Kappa_RecordInitialSearch(searchParams, queryBlk, queryInfo, sbp, scoringParams);
  2249.   localScalingFactor = Kappa_RescaleSearch(searchParams, queryBlk, queryInfo, sbp, scoringParams);
  2250.   for(index = 0; index < hitList->hsplist_count; index++) {
  2251.     /* for all matching sequences */
  2252.     Kappa_MatchingSequence matchingSeq; /* the data for a matching
  2253.                                          * database sequence */
  2254.     BlastHSPList* thisMatch = hitList->hsplist_array[index];
  2255.     if(thisMatch->hsp_array == NULL) {
  2256.       continue;
  2257.     }
  2258.     if(SWheapWillAcceptOnlyBelowCutoff(&significantMatches)) {
  2259.       /* Only matches with evalue <= psiOptions->inclusion_ethresh will be saved */
  2260.       /* e-value for a sequence is the smallest e-value among the hsps
  2261.        * matching a region of the sequence to the query */
  2262.       double minEvalue = BlastHitsGetBestEvalue(thisMatch);  /* FIXME, do we have this on new structures? */
  2263.       if(minEvalue > (EVALUE_STRETCH * psiOptions->inclusion_ethresh)) {
  2264.         /* This match is likely to have an evalue > options->inclusion_ethresh
  2265.          * and therefore, we assume that all other matches with higher
  2266.          * input evalues are also unlikely to get sufficient
  2267.          * improvement in a redone alignment */
  2268.         break;
  2269.       }
  2270.     }
  2271.     /* Get the sequence for this match */
  2272.     Kappa_MatchingSequenceInitialize(&matchingSeq, seqSrc,
  2273.                                      thisMatch->oid);
  2274.     if(0 == Kappa_AdjustSearch(searchParams, queryLength,
  2275.                          matchingSeq.filteredSequence,
  2276.                          matchingSeq.length, matrix)) {
  2277.       /* Kappa_AdjustSearch ran without error. Compute the new alignments. */
  2278.       if(SmithWaterman) {
  2279.         /* We are performing a Smith-Waterman alignment */
  2280.         double newSwEvalue; /* the evalue computed by the SW algorithm */
  2281.         Int4 aSwScore;    /* a score computed by the SW algorithm */
  2282.         Int4 matchStart, queryStart;    /* Start positions of a local
  2283.                                          * S-W alignment */
  2284.         Int4 queryEnd, matchEnd;        /* End positions of a local
  2285.                                          * S-W alignment */
  2286.         Kappa_ForbiddenRangesClear(&forbidden);
  2287.         newSwEvalue =
  2288.           BLbasicSmithWatermanScoreOnly(matchingSeq.filteredSequence,
  2289.                                         matchingSeq.length, query,
  2290.                                         queryLength, matrix,
  2291.                                         scoringParams->gap_open,
  2292.                                         scoringParams->gap_extend, &matchEnd,
  2293.                                         &queryEnd, &aSwScore, kbp,
  2294.                                         queryInfo->eff_searchsp_array[0],
  2295.                                         positionBased);
  2296.         if(newSwEvalue <= hitsavingOptions->expect_value &&
  2297.            SWheapWouldInsert(&significantMatches, newSwEvalue ) ) {
  2298.           /* The initial local alignment is significant. Continue the
  2299.            * computation */
  2300.           Kappa_MatchRecord aSwMatch;   /* the newly computed
  2301.                                          * alignments of the query to
  2302.                                          * the current database
  2303.                                          * sequence */
  2304.         
  2305.           Kappa_MatchRecordInitialize(&aSwMatch, newSwEvalue, aSwScore,
  2306.                                       matchingSeq.sequence,
  2307.                                       thisMatch->oid);
  2308.           BLSmithWatermanFindStart(matchingSeq.filteredSequence,
  2309.                                    matchingSeq.length, query, matrix, 
  2310.                                    scoringParams->gap_open,
  2311.                                    scoringParams->gap_extend, matchEnd, queryEnd,
  2312.                                    aSwScore, &matchStart, &queryStart,
  2313.                                    positionBased);
  2314.           do {
  2315.             /* score computed by an x-drop alignment (usually the same
  2316.              * as aSwScore */
  2317.             Int4 newXdropScore;  
  2318.             /* Lengths of the alignment  as recomputed by an x-drop alignment,
  2319.                in the query and the match*/
  2320.             Int4 queryAlignmentExtent, matchAlignmentExtent;
  2321.             /* Alignment information (script) returned by a x-drop
  2322.              * alignment algorithm */
  2323.             Int4 *reverseAlignScript=NULL;   
  2324.             gapAlign->gap_x_dropoff =
  2325.               (Int4) (extendParams->gap_x_dropoff_final * localScalingFactor);
  2326.             Kappa_SWFindFinalEndsUsingXdrop(query, queryLength, queryStart,
  2327.                                             queryEnd,
  2328.                                             matchingSeq.filteredSequence,
  2329.                                             matchingSeq.length, matchStart,
  2330.                                             matchEnd, gapAlign, scoringParams,
  2331.                                             aSwScore, localScalingFactor,
  2332.                                             &queryAlignmentExtent, &matchAlignmentExtent,
  2333.                                             &reverseAlignScript,
  2334.                                             &newXdropScore);
  2335.             Kappa_MatchRecordInsertSwAlign(&aSwMatch, newXdropScore,
  2336.                                            newSwEvalue, kbp->Lambda,
  2337.                                            kbp->logK, localScalingFactor,
  2338.                                            matchStart, matchAlignmentExtent,
  2339.                                            queryStart, queryAlignmentExtent,
  2340.                                            reverseAlignScript, query);
  2341.             sfree(reverseAlignScript);
  2342.             Kappa_ForbiddenRangesPush(&forbidden, queryStart, queryAlignmentExtent,
  2343.                                       matchStart, matchAlignmentExtent);
  2344.             if(thisMatch->hspcnt > 1) {
  2345.               /* There are more HSPs */
  2346.               newSwEvalue =
  2347.                 BLspecialSmithWatermanScoreOnly(matchingSeq.filteredSequence,
  2348.                                                 matchingSeq.length, query,
  2349.                                                 queryLength, matrix,
  2350.                                                 scoringParams->gap_open,
  2351.                                                 scoringParams->gap_extend,
  2352.                                                 &matchEnd, &queryEnd,
  2353.                                                 &aSwScore, kbp,
  2354.                                                 queryInfo->eff_searchsp_array[0],
  2355.                                                 forbidden.numForbidden,
  2356.                                                 forbidden.ranges,
  2357.                                                 positionBased);
  2358.               if(newSwEvalue <= hitsavingOptions->expect_value) {
  2359.                 /* The next local alignment is significant */
  2360.                 BLspecialSmithWatermanFindStart(matchingSeq.filteredSequence,
  2361.                                                 matchingSeq.length, query,
  2362.                                                 matrix,
  2363.                                                 scoringParams->gap_open,
  2364.                                                 scoringParams->gap_extend,
  2365.                                                 matchEnd, queryEnd, aSwScore,
  2366.                                                 &matchStart, &queryStart,
  2367.                                                 forbidden.numForbidden,
  2368.                                                 forbidden.ranges,
  2369.                                                 positionBased);
  2370.               }
  2371.               /* end if the next local alignment is significant */
  2372.             }
  2373.             /* end if there are more HSPs */
  2374.           } while(thisMatch->hspcnt > 1 &&
  2375.                   newSwEvalue <= hitsavingOptions->expect_value);
  2376.           /* end do..while there are more HSPs and the next local alignment
  2377.            * is significant */
  2378.           SWheapInsert(&significantMatches, &aSwMatch);
  2379.         }
  2380.         /* end if the initial local alignment is significant */
  2381.       } else {
  2382.         /* We are not doing a Smith-Waterman alignment */
  2383.         gapAlign->gap_x_dropoff = 
  2384.           (Int4) (extendParams->gap_x_dropoff_final * localScalingFactor);
  2385.         /* recall that index is the counter corresponding to
  2386.          * thisMatch; by aliasing, thisMatch will get updated during
  2387.          * the following call to BlastGetGapAlgnTbck, so that
  2388.          * thisMatch stores newly computed alignments between the
  2389.          * query and the matching sequence number index */
  2390.           if ((status=Blast_TracebackFromHSPList(k_program_name, thisMatch, queryBlk, 
  2391.              matchingSeq.seq_blk, queryInfo, gapAlign, sbp, scoringParams, 
  2392.              extendOptions, hitsavingParams, NULL)) != 0)
  2393.              return status;
  2394.         if(thisMatch->hspcnt) {
  2395.           /* There are alignments of the query to this matching sequence */
  2396.           double bestEvalue = BlastHitsGetBestEvalue(thisMatch);  
  2397.           if(bestEvalue <= hitsavingOptions->expect_value &&
  2398.              SWheapWouldInsert(&significantMatches, bestEvalue ) ) {
  2399.             /* The best alignment is significant */
  2400.             Int4 alignIndex;            /* Iteration index */
  2401.             Int4 numNewAlignments;      /* the number of alignments
  2402.                                          * just computed */
  2403.             Kappa_MatchRecord matchRecord;      /* the newly computed
  2404.                                                  * alignments of the
  2405.                                                  * query to the
  2406.                                                  * current database
  2407.                                                  * sequence */
  2408.             Int4 bestScore;      /* the score of the highest
  2409.                                          * scoring alignment */
  2410.             numNewAlignments = thisMatch->hspcnt;  
  2411.             bestScore =
  2412.               (Int4) BLAST_Nint(((double) thisMatch->hsp_array[0]->score) /
  2413.                        localScalingFactor);
  2414.             Kappa_MatchRecordInitialize(&matchRecord, bestEvalue, bestScore,
  2415.                                         matchingSeq.sequence,
  2416.                                         thisMatch->oid);
  2417.             for(alignIndex = 0; alignIndex < numNewAlignments; alignIndex++) {
  2418.               Kappa_MatchRecordInsertHSP(&matchRecord, 
  2419.                                          &(thisMatch->hsp_array[alignIndex]),
  2420.                                          kbp->Lambda, kbp->logK,
  2421.                                          localScalingFactor, query);
  2422.             }
  2423.             /* end for all alignments of this matching sequence */
  2424.             SWheapInsert(&significantMatches, &matchRecord);
  2425.           }
  2426.           /* end if the best alignment is significant */
  2427.         }
  2428.         /* end there are alignments of the query to this matching sequence */
  2429.       }
  2430.       /* end else we are not doing a Smith-Waterman alignment */
  2431.     }
  2432.     /* end if Kappa_AdjustSearch ran without error */
  2433.     Kappa_MatchingSequenceRelease(&matchingSeq);
  2434.   }
  2435.   /* end for all matching sequences */
  2436.   Blast_HitListHSPListsFree(hitList); 
  2437.   /* All HSP's have been saved on other structs, free HSPList before repopulating below. */
  2438.   {
  2439.     SWResults *SWAligns;        /* All new alignments, concatenated
  2440.                                    into a single, flat list */
  2441.     SWAligns = SWheapToFlatList(&significantMatches);
  2442.     if(SWAligns != NULL) {
  2443.       newConvertSWalignsUpdateHitList(SWAligns, hitList);
  2444.     }
  2445.     SWAligns = SWResultsFree(SWAligns);
  2446.   }
  2447.   /* Clean up */
  2448.   SWheapRelease(&significantMatches);
  2449.   if(SmithWaterman) 
  2450.     Kappa_ForbiddenRangesRelease(&forbidden);
  2451.   Kappa_RestoreSearch(searchParams, sbp, matrix, scoringParams);
  2452.   Kappa_SearchParametersFree(&searchParams);
  2453.   gapAlign = BLAST_GapAlignStructFree(gapAlign);
  2454.   return 0;
  2455. }