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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: link_hsps.c,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 18:08:05  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.35
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: link_hsps.c,v 1000.3 2004/06/01 18:08:05 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's offical duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Ilya Dondoshansky
  35.  *
  36.  */
  37. /** @file link_hsps.c
  38.  * Functions to link with use of sum statistics
  39.  */
  40. static char const rcsid[] = 
  41.     "$Id: link_hsps.c,v 1000.3 2004/06/01 18:08:05 gouriano Exp $";
  42. #include <algo/blast/core/link_hsps.h>
  43. #include <algo/blast/core/blast_util.h>
  44. /** Methods used to "order" the HSP's. */
  45. #define BLAST_NUMBER_OF_ORDERING_METHODS 2
  46. typedef enum LinkOrderingMethod {
  47.    BLAST_SMALL_GAPS = 0,
  48.    BLAST_LARGE_GAPS
  49. } LinkOrderingMethod;
  50. /* Forward declaration */
  51. struct LinkHSPStruct;
  52. /** The following structure is used in "link_hsps" to decide between
  53.  * two different "gapping" models.  Here link is used to hook up
  54.  * a chain of HSP's, num is the number of links, and sum is the sum score.
  55.  * Once the best gapping model has been found, this information is
  56.  * transferred up to the LinkHSPStruct.  This structure should not be
  57.  * used outside of the function link_hsps.
  58. */
  59. typedef struct BlastHSPLink {
  60.    struct LinkHSPStruct* link[BLAST_NUMBER_OF_ORDERING_METHODS]; /**< Best 
  61.                                                choice of HSP to link with */
  62.    Int2 num[BLAST_NUMBER_OF_ORDERING_METHODS]; /**< number of HSP in the
  63.                                                   ordering. */
  64.    Int4 sum[BLAST_NUMBER_OF_ORDERING_METHODS]; /**< Sum-Score of HSP. */
  65.    double xsum[BLAST_NUMBER_OF_ORDERING_METHODS]; /**< Sum-Score of HSP,
  66.                                      multiplied by the appropriate Lambda. */
  67.    Int4 changed; /**< Has the link been changed since previous access? */
  68. } BlastHSPLink;
  69. /** Structure containing all information internal to the process of linking
  70.  * HSPs.
  71.  */
  72. typedef struct LinkHSPStruct {
  73.    BlastHSP* hsp;      /**< Specific HSP this structure corresponds to */
  74.    struct LinkHSPStruct* prev;         /**< Previous HSP in a set, if any */
  75.    struct LinkHSPStruct* next;         /**< Next HSP in a set, if any */ 
  76.    BlastHSPLink  hsp_link; /**< Auxiliary structure for keeping track of sum
  77.                               scores, etc. */
  78.    Boolean linked_set;     /**< Is this HSp part of a linked set? */
  79.    Boolean start_of_chain; /**< If TRUE, this HSP starts a chain along the
  80.                               "link" pointer. */
  81.    Int4 linked_to;         /**< Where this HSP is linked to? */
  82.    Int4 sumscore;          /**< Sumscore of a set of "linked" HSP's. */
  83.    Int2 ordering_method;   /**< Which method (max or no max for gaps) was 
  84.                               used for linking HSPs? */
  85.    Int4 q_offset_trim;     /**< Start of trimmed hsp in query */
  86.    Int4 q_end_trim;        /**< End of trimmed HSP in query */
  87.    Int4 s_offset_trim;     /**< Start of trimmed hsp in subject */
  88.    Int4 s_end_trim;        /**< End of trimmed HSP in subject */
  89. } LinkHSPStruct;
  90. #define WINDOW_SIZE 20
  91. static double 
  92. SumHSPEvalue(Uint1 program_number, BlastScoreBlk* sbp, 
  93.    BlastQueryInfo* query_info, BLAST_SequenceBlk* subject, 
  94.    const BlastHitSavingParameters* hit_params, 
  95.    LinkHSPStruct* head_hsp, LinkHSPStruct* hsp, Int4* sumscore)
  96. {
  97.    double gap_prob, gap_decay_rate, sum_evalue, score_prime;
  98.    Int2 num;
  99.    Int4 subject_eff_length, query_eff_length, length_adjustment;
  100.    Int4 context = head_hsp->hsp->context;
  101.    double eff_searchsp;
  102.    gap_prob = hit_params->gap_prob;
  103.    gap_decay_rate = hit_params->gap_decay_rate;
  104.    num = head_hsp->hsp->num + hsp->hsp->num;
  105.    length_adjustment = query_info->length_adjustments[context];
  106.    subject_eff_length = 
  107.       MAX((subject->length - length_adjustment), 1);
  108.    if (program_number == blast_type_tblastn) 
  109.       subject_eff_length /= 3;
  110.    subject_eff_length = MAX(subject_eff_length, 1);
  111.    query_eff_length = 
  112.       MAX(BLAST_GetQueryLength(query_info, context) - length_adjustment, 1);
  113.    
  114.    *sumscore = MAX(hsp->hsp->score, hsp->sumscore) + 
  115.       MAX(head_hsp->hsp->score, head_hsp->sumscore);
  116.    score_prime = *sumscore * sbp->kbp_gap[context]->Lambda;
  117.    sum_evalue =
  118.        BLAST_UnevenGapSumE(sbp->kbp_gap[context], 2*WINDOW_SIZE,
  119.                            hit_params->options->longest_intron + WINDOW_SIZE,
  120.                            num, score_prime,
  121.                            query_eff_length, subject_eff_length,
  122.                            BLAST_GapDecayDivisor(gap_decay_rate, num));
  123.    eff_searchsp = ((double) subject_eff_length) * query_eff_length;
  124.    
  125.    sum_evalue *= 
  126.       ((double) query_info->eff_searchsp_array[context]) / eff_searchsp;
  127.    return sum_evalue;
  128. }
  129. /** Sort the HSP's by starting position of the query.  Called by qsort.  
  130.  * The first function sorts in forward, the second in reverse order.
  131. */
  132. static int
  133. fwd_compare_hsps(const void* v1, const void* v2)
  134. {
  135. BlastHSP* h1,* h2;
  136. LinkHSPStruct** hp1,** hp2;
  137. hp1 = (LinkHSPStruct**) v1;
  138. hp2 = (LinkHSPStruct**) v2;
  139. h1 = (*hp1)->hsp;
  140. h2 = (*hp2)->hsp;
  141. if (h1->context < h2->context)
  142.       return -1;
  143.    else if (h1->context > h2->context)
  144.       return 1;
  145. if (h1->query.offset < h2->query.offset) 
  146. return -1;
  147. if (h1->query.offset > h2->query.offset) 
  148. return 1;
  149. /* Necessary in case both HSP's have the same query offset. */
  150. if (h1->subject.offset < h2->subject.offset) 
  151. return -1;
  152. if (h1->subject.offset > h2->subject.offset) 
  153. return 1;
  154. return 0;
  155. }
  156. /** Sort the HSP's by starting position of the query.  Called by qsort.  
  157.  * The first function sorts in forward, the second in reverse order.
  158. */
  159. static int
  160. fwd_compare_hsps_transl(const void* v1, const void* v2)
  161. {
  162. BlastHSP* h1,* h2;
  163. LinkHSPStruct** hp1,** hp2;
  164.    Int4 context1, context2;
  165. hp1 = (LinkHSPStruct**) v1;
  166. hp2 = (LinkHSPStruct**) v2;
  167. h1 = (*hp1)->hsp;
  168. h2 = (*hp2)->hsp;
  169.    context1 = h1->context/3;
  170.    context2 = h2->context/3;
  171.    if (context1 < context2)
  172.       return 1;
  173.    else if (context1 > context2)
  174.       return -1;
  175. if (h1->query.offset < h2->query.offset) 
  176. return -1;
  177. if (h1->query.offset > h2->query.offset) 
  178. return 1;
  179. /* Necessary in case both HSP's have the same query offset. */
  180. if (h1->subject.offset < h2->subject.offset) 
  181. return -1;
  182. if (h1->subject.offset > h2->subject.offset) 
  183. return 1;
  184. return 0;
  185. }
  186. /* Comparison function based on end position in the query */
  187. static int
  188. end_compare_hsps(const void* v1, const void* v2)
  189. {
  190. BlastHSP* h1,* h2;
  191. LinkHSPStruct** hp1,** hp2;
  192. hp1 = (LinkHSPStruct**) v1;
  193. hp2 = (LinkHSPStruct**) v2;
  194. h1 = (*hp1)->hsp;
  195. h2 = (*hp2)->hsp;
  196.    if (h1->context < h2->context)
  197.       return 1;
  198.    else if (h1->context > h2->context)
  199.       return -1;
  200. if (h1->query.end < h2->query.end) 
  201. return -1;
  202. if (h1->query.end > h2->query.end) 
  203. return 1;
  204. /* Necessary in case both HSP's have the same query end. */
  205. if (h1->subject.end < h2->subject.end) 
  206. return -1;
  207. if (h1->subject.end > h2->subject.end) 
  208. return 1;
  209. return 0;
  210. }
  211. static int
  212. sumscore_compare_hsps(const void* v1, const void* v2)
  213. {
  214. LinkHSPStruct* h1,* h2;
  215. LinkHSPStruct** hp1,** hp2;
  216.    Int4 score1, score2;
  217. hp1 = (LinkHSPStruct**) v1;
  218. hp2 = (LinkHSPStruct**) v2;
  219. h1 = *hp1;
  220. h2 = *hp2;
  221. if (h1 == NULL || h2 == NULL)
  222. return 0;
  223.    score1 = MAX(h1->sumscore, h1->hsp->score);
  224.    score2 = MAX(h2->sumscore, h2->hsp->score);
  225. if (score1 < score2) 
  226. return 1;
  227. if (score1 > score2)
  228. return -1;
  229. return 0;
  230. }
  231. /* The following function should be used only for new tblastn. 
  232.    Current implementation does not allow its use in two sequences BLAST */
  233. #define MAX_SPLICE_DIST 5
  234. static Boolean
  235. FindSpliceJunction(Uint1* subject_seq, BlastHSP* hsp1, BlastHSP* hsp2)
  236. {
  237.    Boolean found = FALSE;
  238.    Int4 overlap, length, i;
  239.    Uint1* nt_seq;
  240.    Uint1 g = 4, t = 8, a = 1; /* ncbi4na values for G, T, A respectively */
  241.    if (!subject_seq)
  242.       return FALSE;
  243.    overlap = hsp1->query.end - hsp2->query.offset;
  244.    if (overlap >= 0) {
  245.       length = 3*overlap + 2;
  246.       nt_seq = &subject_seq[hsp1->subject.end - 3*overlap];
  247.    } else {
  248.       length = MAX_SPLICE_DIST;
  249.       nt_seq = &subject_seq[hsp1->subject.end];
  250.    }
  251.    
  252.    for (i=0; i<length-1; i++) {
  253.       if (nt_seq[i] == g && nt_seq[i+1] == t) {
  254.          found = TRUE;
  255.          break;
  256.       }
  257.    }
  258.       
  259.    if (!found) 
  260.       return FALSE;
  261.    else
  262.       found = FALSE;
  263.    if (overlap >= 0) 
  264.       nt_seq = &subject_seq[hsp2->subject.offset - 2];
  265.    else 
  266.       nt_seq = &subject_seq[hsp2->subject.offset - MAX_SPLICE_DIST];
  267.    for (i=0; i<length-1; i++) {
  268.       if (nt_seq[i] == a && nt_seq[i+1] == g) {
  269.          found = TRUE;
  270.          break;
  271.       }
  272.    }
  273.    return found;
  274. }
  275. /* Find an HSP with offset closest, but not smaller/larger than a given one.
  276.  */
  277. static Int4 hsp_binary_search(LinkHSPStruct** hsp_array, Int4 size, 
  278.                               Int4 offset, Boolean right)
  279. {
  280.    Int4 index, begin, end, coord;
  281.    
  282.    begin = 0;
  283.    end = size;
  284.    while (begin < end) {
  285.       index = (begin + end) / 2;
  286.       if (right) 
  287.          coord = hsp_array[index]->hsp->query.offset;
  288.       else
  289.          coord = hsp_array[index]->hsp->query.end;
  290.       if (coord >= offset) 
  291.          end = index;
  292.       else
  293.          begin = index + 1;
  294.    }
  295.    return end;
  296. }
  297. static int
  298. rev_compare_hsps(const void *v1, const void *v2)
  299. {
  300. BlastHSP* h1,* h2;
  301. LinkHSPStruct** hp1,** hp2;
  302. hp1 = (LinkHSPStruct**) v1;
  303. hp2 = (LinkHSPStruct**) v2;
  304. h1 = (*hp1)->hsp;
  305. h2 = (*hp2)->hsp;
  306.    if (h1->context > h2->context)
  307.       return 1;
  308.    else if (h1->context < h2->context)
  309.       return -1;
  310. if (h1->query.offset < h2->query.offset) 
  311. return  1;
  312. if (h1->query.offset > h2->query.offset) 
  313. return -1;
  314. return 0;
  315. }
  316. static int
  317. rev_compare_hsps_transl(const void *v1, const void *v2)
  318. {
  319. BlastHSP* h1,* h2;
  320. LinkHSPStruct** hp1,** hp2;
  321.    Int4 context1, context2;
  322. hp1 = (LinkHSPStruct**) v1;
  323. hp2 = (LinkHSPStruct**) v2;
  324. h1 = (*hp1)->hsp;
  325. h2 = (*hp2)->hsp;
  326.    context1 = h1->context/3;
  327.    context2 = h2->context/3;
  328.    if (context1 > context2)
  329.       return 1;
  330.    else if (context1 < context2)
  331.       return -1;
  332. if (h1->query.offset < h2->query.offset) 
  333. return  1;
  334. if (h1->query.offset > h2->query.offset) 
  335. return -1;
  336. return 0;
  337. }
  338. static int
  339. rev_compare_hsps_tbn(const void *v1, const void *v2)
  340. {
  341. BlastHSP* h1,* h2;
  342. LinkHSPStruct** hp1,** hp2;
  343. hp1 = (LinkHSPStruct**) v1;
  344. hp2 = (LinkHSPStruct**) v2;
  345. h1 = (*hp1)->hsp;
  346. h2 = (*hp2)->hsp;
  347.    if (h1->context > h2->context)
  348.       return 1;
  349.    else if (h1->context < h2->context)
  350.       return -1;
  351. if (SIGN(h1->subject.frame) != SIGN(h2->subject.frame))
  352. {
  353. if (h1->subject.frame > h2->subject.frame)
  354. return 1;
  355. else
  356. return -1;
  357. }
  358. if (h1->query.offset < h2->query.offset) 
  359. return  1;
  360. if (h1->query.offset > h2->query.offset) 
  361. return -1;
  362. return 0;
  363. }
  364. static int
  365. rev_compare_hsps_tbx(const void *v1, const void *v2)
  366. {
  367. BlastHSP* h1,* h2;
  368. LinkHSPStruct** hp1,** hp2;
  369.    Int4 context1, context2;
  370. hp1 = (LinkHSPStruct**) v1;
  371. hp2 = (LinkHSPStruct**) v2;
  372. h1 = (*hp1)->hsp;
  373. h2 = (*hp2)->hsp;
  374.    context1 = h1->context/3;
  375.    context2 = h2->context/3;
  376.    if (context1 > context2)
  377.       return 1;
  378.    else if (context1 < context2)
  379.       return -1;
  380.    
  381. if (SIGN(h1->subject.frame) != SIGN(h2->subject.frame))
  382. {
  383. if (h1->subject.frame > h2->subject.frame)
  384. return 1;
  385. else
  386. return -1;
  387. }
  388. if (h1->query.offset < h2->query.offset) 
  389. return  1;
  390. if (h1->query.offset > h2->query.offset) 
  391. return -1;
  392. return 0;
  393. }
  394. /** The helper array contains the info used frequently in the inner 
  395.  * for loops of the HSP linking algorithm.
  396.  * One array of helpers will be allocated for each thread.
  397.  */
  398. typedef struct LinkHelpStruct {
  399.   LinkHSPStruct* ptr;
  400.   Int4 q_off_trim;
  401.   Int4 s_off_trim;
  402.   Int4 sum[BLAST_NUMBER_OF_ORDERING_METHODS];
  403.   Int4 maxsum1;
  404.   Int4 next_larger;
  405. } LinkHelpStruct;
  406. static LinkHSPStruct* LinkHSPStructReset(LinkHSPStruct* lhsp)
  407. {
  408.    BlastHSP* hsp;
  409.    if (!lhsp) {
  410.       lhsp = (LinkHSPStruct*) calloc(1, sizeof(LinkHSPStruct));
  411.       lhsp->hsp = (BlastHSP*) calloc(1, sizeof(BlastHSP));
  412.    } else {
  413.       if (!lhsp->hsp) {
  414.          hsp = (BlastHSP*) calloc(1, sizeof(BlastHSP));
  415.       } else {
  416.          hsp = lhsp->hsp;
  417.          memset(hsp, 0, sizeof(BlastHSP));
  418.       }
  419.       memset(lhsp, 0, sizeof(LinkHSPStruct));
  420.       lhsp->hsp = hsp;
  421.    }
  422.    return lhsp;
  423. }
  424. static Int2
  425. link_hsps(Uint1 program_number, BlastHSPList* hsp_list, 
  426.    BlastQueryInfo* query_info, BLAST_SequenceBlk* subject,
  427.    BlastScoreBlk* sbp, const BlastHitSavingParameters* hit_params,
  428.    Boolean gapped_calculation)
  429. {
  430. LinkHSPStruct* H,* H2,* best[2],* first_hsp,* last_hsp,** hp_frame_start;
  431. LinkHSPStruct* hp_start = NULL;
  432.    BlastHSP* hsp;
  433.    BlastHSP** hsp_array;
  434. Blast_KarlinBlk** kbp;
  435. Int4 maxscore, cutoff[2];
  436. Boolean linked_set, ignore_small_gaps;
  437. double gap_decay_rate, gap_prob, prob[2];
  438. Int4 index, index1, num_links, frame_index;
  439.    LinkOrderingMethod ordering_method;
  440.    Int4 num_query_frames, num_subject_frames;
  441. Int4 *hp_frame_number;
  442. Int4 gap_size, number_of_hsps, total_number_of_hsps;
  443.    Int4 query_length, subject_length, length_adjustment;
  444. LinkHSPStruct* link;
  445. Int4 H2_index,H_index;
  446. Int4 i;
  447. Int4 max_q_diff;
  448.   Int4 path_changed;  /* will be set if an element is removed that may change an existing path */
  449.   Int4 first_pass, use_current_max; 
  450. LinkHelpStruct *lh_helper=0;
  451.    Int4 lh_helper_size;
  452. Int4 query_context; /* AM: to support query concatenation. */
  453.    Boolean translated_query;
  454.    LinkHSPStruct** link_hsp_array;
  455. if (hsp_list == NULL)
  456. return -1;
  457.    hsp_array = hsp_list->hsp_array;
  458.    lh_helper_size = MAX(1024,hsp_list->hspcnt+5);
  459.    lh_helper = (LinkHelpStruct *) 
  460.       calloc(lh_helper_size, sizeof(LinkHelpStruct));
  461. if (gapped_calculation) 
  462. kbp = sbp->kbp_gap;
  463. else
  464. kbp = sbp->kbp;
  465. total_number_of_hsps = hsp_list->hspcnt;
  466. number_of_hsps = total_number_of_hsps;
  467. gap_size = hit_params->gap_size;
  468. gap_prob = hit_params->gap_prob;
  469. gap_decay_rate = hit_params->gap_decay_rate;
  470. translated_query = (program_number == blast_type_blastx || 
  471.                        program_number == blast_type_tblastx);
  472.    if (program_number == blast_type_tblastn ||
  473.        program_number == blast_type_tblastx)
  474.       num_subject_frames = NUM_STRANDS;
  475.    else
  476.       num_subject_frames = 1;
  477.    link_hsp_array = 
  478.       (LinkHSPStruct**) malloc(total_number_of_hsps*sizeof(LinkHSPStruct*));
  479.    for (index = 0; index < total_number_of_hsps; ++index) {
  480.       link_hsp_array[index] = (LinkHSPStruct*) calloc(1, sizeof(LinkHSPStruct));
  481.       link_hsp_array[index]->hsp = hsp_array[index];
  482.    }
  483.    /* Sort by (reverse) position. */
  484.    if (translated_query) {
  485.       qsort(link_hsp_array,total_number_of_hsps,sizeof(LinkHSPStruct*), 
  486.             rev_compare_hsps_tbx);
  487.    } else {
  488.       qsort(link_hsp_array,total_number_of_hsps,sizeof(LinkHSPStruct*), 
  489.             rev_compare_hsps_tbn);
  490.    }
  491. cutoff[0] = hit_params->cutoff_small_gap;
  492. cutoff[1] = hit_params->cutoff_big_gap;
  493. ignore_small_gaps = hit_params->ignore_small_gaps;
  494. if (translated_query)
  495. num_query_frames = NUM_STRANDS*query_info->num_queries;
  496. else
  497. num_query_frames = query_info->num_queries;
  498.    
  499.    hp_frame_start = 
  500.        calloc(num_subject_frames*num_query_frames, sizeof(LinkHSPStruct*));
  501.    hp_frame_number = calloc(num_subject_frames*num_query_frames, sizeof(Int4));
  502. /* hook up the HSP's */
  503. hp_frame_start[0] = link_hsp_array[0];
  504. /* Put entries with different frame parity into separate 'query_frame's. -cfj */
  505. {
  506.   Int4 cur_frame=0;
  507.      for (index=0;index<number_of_hsps;index++) 
  508.      {
  509.         H=link_hsp_array[index];
  510.         H->start_of_chain = FALSE;
  511.         hp_frame_number[cur_frame]++;
  512.         H->prev= index ? link_hsp_array[index-1] : NULL;
  513.         H->next= index<(number_of_hsps-1) ? link_hsp_array[index+1] : NULL;
  514.         if (H->prev != NULL && 
  515.             ((H->hsp->context/3) != (H->prev->hsp->context/3) ||
  516.              (SIGN(H->hsp->subject.frame) != SIGN(H->prev->hsp->subject.frame))))
  517.         { /* If frame switches, then start new list. */
  518.            hp_frame_number[cur_frame]--;
  519.            hp_frame_number[++cur_frame]++;
  520.            hp_frame_start[cur_frame] = H;
  521.            H->prev->next = NULL;
  522.            H->prev = NULL;
  523.         }
  524.      }
  525.      num_query_frames = cur_frame+1;
  526. }
  527. /* max_q_diff is the maximum amount q.offset can differ from q.offset_trim */
  528. /* This is used to break out of H2 loop early */
  529.    for (index=0;index<number_of_hsps;index++) 
  530.    {
  531.       H = link_hsp_array[index];
  532. hsp = H->hsp;
  533. H->q_offset_trim = hsp->query.offset + MIN(((hsp->query.length)/4), 5);
  534. H->q_end_trim = hsp->query.end - MIN(((hsp->query.length)/4), 5);
  535. H->s_offset_trim = 
  536.          hsp->subject.offset + MIN(((hsp->subject.length)/4), 5);
  537. H->s_end_trim = hsp->subject.end - MIN(((hsp->subject.length)/4), 5);
  538.    }     
  539.    max_q_diff = 5;
  540. for (frame_index=0; frame_index<num_query_frames; frame_index++)
  541. {
  542.       hp_start = LinkHSPStructReset(hp_start);
  543.       hp_start->next = hp_frame_start[frame_index];
  544.       hp_frame_start[frame_index]->prev = hp_start;
  545.       number_of_hsps = hp_frame_number[frame_index];
  546.       query_context = hp_start->next->hsp->context;
  547.       length_adjustment = query_info->length_adjustments[query_context];
  548.       query_length = BLAST_GetQueryLength(query_info, query_context);
  549.       query_length = MAX(query_length - length_adjustment, 1);
  550.       subject_length = subject->length; /* in nucleotides even for tblast[nx] */
  551.       /* If subject is translated, length adjustment is given in nucleotide
  552.          scale. */
  553.       if (program_number == blast_type_tblastn || 
  554.           program_number == blast_type_tblastx)
  555.       {
  556.          length_adjustment /= CODON_LENGTH;
  557.          subject_length /= CODON_LENGTH;
  558.       }
  559.       subject_length = MAX(subject_length - length_adjustment, 1);
  560.       lh_helper[0].ptr = hp_start;
  561.       lh_helper[0].q_off_trim = 0;
  562.       lh_helper[0].s_off_trim = 0;
  563.       lh_helper[0].maxsum1  = -10000;
  564.       lh_helper[0].next_larger  = 0;
  565.       
  566.       /* lh_helper[0]  = empty     = additional end marker
  567.        * lh_helper[1]  = hsp_start = empty entry used in original code
  568.        * lh_helper[2]  = hsp_array->next = hsp_array[0]
  569.        * lh_helper[i]  = ... = hsp_array[i-2] (for i>=2) 
  570.        */
  571.       first_pass=1;    /* do full search */
  572.       path_changed=1;
  573.       for (H=hp_start->next; H!=NULL; H=H->next) 
  574.          H->hsp_link.changed=1;
  575.       while (number_of_hsps > 0)
  576.       {
  577.          Int4 max[3];
  578.          max[0]=max[1]=max[2]=-10000;
  579.          /* Initialize the 'best' parameter */
  580.          best[0] = best[1] = NULL;
  581.          
  582.          
  583.          /* See if we can avoid recomputing all scores:
  584.           *  - Find the max paths (based on old scores). 
  585.           *  - If no paths were changed by removal of nodes (ie research==0) 
  586.           *    then these max paths are still the best.
  587.           *  - else if these max paths were unchanged, then they are still the best.
  588.           */
  589.          use_current_max=0;
  590.          if (!first_pass){
  591.             Int4 max0,max1;
  592.             /* Find the current max sums */
  593.             if(!ignore_small_gaps){
  594.                max0 = -cutoff[0];
  595.                max1 = -cutoff[1];
  596.                for (H=hp_start->next; H!=NULL; H=H->next) {
  597.                   Int4 sum0=H->hsp_link.sum[0];
  598.                   Int4 sum1=H->hsp_link.sum[1];
  599.                   if(sum0>=max0)
  600.                   {
  601.                      max0=sum0;
  602.                      best[0]=H;
  603.                   }
  604.                   if(sum1>=max1)
  605.                   {
  606.                      max1=sum1;
  607.                      best[1]=H;
  608.                   }
  609.                }
  610.             } else {
  611.                maxscore = -cutoff[1];
  612.                for (H=hp_start->next; H!=NULL; H=H->next) {
  613.                   Int4  sum=H->hsp_link.sum[1];
  614.                   if(sum>=maxscore)
  615.                   {
  616.                      maxscore=sum;
  617.                      best[1]=H;
  618.                   }
  619.                }
  620.             }
  621.             if(path_changed==0){
  622.                /* No path was changed, use these max sums. */
  623.                use_current_max=1;
  624.             }
  625.             else{
  626.                /* If max path hasn't chaged, we can use it */
  627.                /* Walk down best, give up if we find a removed item in path */
  628.                use_current_max=1;
  629.                if(!ignore_small_gaps){
  630.                   for (H=best[0]; H!=NULL; H=H->hsp_link.link[0]) 
  631.                      if (H->linked_to==-1000) {use_current_max=0; break;}
  632.                }
  633.                if(use_current_max)
  634.                   for (H=best[1]; H!=NULL; H=H->hsp_link.link[1]) 
  635.                      if (H->linked_to==-1000) {use_current_max=0; break;}
  636.                
  637.             }
  638.          }
  639.          /* reset helper_info */
  640.          /* Inside this while loop, the linked list order never changes 
  641.           * So here we initialize an array of commonly used info, 
  642.           * and in this loop we access these arrays instead of the actual list 
  643.           */
  644.          if(!use_current_max){
  645.             for (H=hp_start,H_index=1; H!=NULL; H=H->next,H_index++) {
  646.                Int4 s_frame = H->hsp->subject.frame;
  647.                Int4 s_off_t = H->s_offset_trim;
  648.                Int4 q_off_t = H->q_offset_trim;
  649.                lh_helper[H_index].ptr = H;
  650.                lh_helper[H_index].q_off_trim = q_off_t;
  651.                lh_helper[H_index].s_off_trim = s_off_t;
  652.                for(i=0;i<BLAST_NUMBER_OF_ORDERING_METHODS;i++)
  653.                   lh_helper[H_index].sum[i] = H->hsp_link.sum[i];
  654.                max[SIGN(s_frame)+1]=
  655.                   MAX(max[SIGN(s_frame)+1],H->hsp_link.sum[1]);
  656.                lh_helper[H_index].maxsum1 =max[SIGN(s_frame)+1];    
  657.                
  658.                /* set next_larger to link back to closest entry with a sum1 
  659.                   larger than this */
  660.                {
  661.                   Int4 cur_sum=lh_helper[H_index].sum[1];
  662.                   Int4 prev = H_index-1;
  663.                   Int4 prev_sum = lh_helper[prev].sum[1];
  664.                   while((cur_sum>=prev_sum) && (prev>0)){
  665.                      prev=lh_helper[prev].next_larger;
  666.                      prev_sum = lh_helper[prev].sum[1];
  667.                   }
  668.                   lh_helper[H_index].next_larger = prev;
  669.                }
  670.                H->linked_to = 0;
  671.             }
  672.             
  673.             lh_helper[1].maxsum1 = -10000;
  674.             
  675.             /****** loop iter for index = 0  **************************/
  676.             if(!ignore_small_gaps)
  677.             {
  678.                index=0;
  679.                maxscore = -cutoff[index];
  680.                H_index = 2;
  681.                for (H=hp_start->next; H!=NULL; H=H->next,H_index++) 
  682.                {
  683.                   Int4 H_hsp_num=0;
  684.                   Int4 H_hsp_sum=0;
  685.                   double H_hsp_xsum=0.0;
  686.                   LinkHSPStruct* H_hsp_link=NULL;
  687.                   if (H->hsp->score > cutoff[index]) {
  688.                      Int4 H_query_etrim = H->q_end_trim;
  689.                      Int4 H_sub_etrim = H->s_end_trim;
  690.                      Int4 H_q_et_gap = H_query_etrim+gap_size;
  691.                      Int4 H_s_et_gap = H_sub_etrim+gap_size;
  692.                      
  693.                      /* We only walk down hits with the same frame sign */
  694.                      /* for (H2=H->prev; H2!=NULL; H2=H2->prev,H2_index--) */
  695.                      for (H2_index=H_index-1; H2_index>1; H2_index=H2_index-1) 
  696.                      {
  697.                         Int4 b1,b2,b4,b5;
  698.                         Int4 q_off_t,s_off_t,sum;
  699.                         
  700.                         /* s_frame = lh_helper[H2_index].s_frame; */
  701.                         q_off_t = lh_helper[H2_index].q_off_trim;
  702.                         s_off_t = lh_helper[H2_index].s_off_trim;
  703.                         
  704.                         /* combine tests to reduce mispredicts -cfj */
  705.                         b1 = q_off_t <= H_query_etrim;
  706.                         b2 = s_off_t <= H_sub_etrim;
  707.                         sum = lh_helper[H2_index].sum[index];
  708.                         
  709.                         
  710.                         b4 = ( q_off_t > H_q_et_gap ) ;
  711.                         b5 = ( s_off_t > H_s_et_gap ) ;
  712.                         
  713.                         /* list is sorted by q_off, so q_off should only increase.
  714.                          * q_off_t can only differ from q_off by max_q_diff
  715.                          * So once q_off_t is large enough (ie it exceeds limit 
  716.                          * by max_q_diff), we can stop.  -cfj 
  717.                          */
  718.                         if(q_off_t > (H_q_et_gap+max_q_diff))
  719.                            break;
  720.                         
  721.                         if (b1|b2|b5|b4) continue;
  722.                         
  723.                         if (sum>H_hsp_sum) 
  724.                         {
  725.                            H2=lh_helper[H2_index].ptr; 
  726.                            H_hsp_num=H2->hsp_link.num[index];
  727.                            H_hsp_sum=H2->hsp_link.sum[index];
  728.                            H_hsp_xsum=H2->hsp_link.xsum[index];
  729.                            H_hsp_link=H2;
  730.                         }
  731.                      } /* end for H2... */
  732.                   }
  733.                   { 
  734.                      Int4 score=H->hsp->score;
  735.                      double new_xsum = H_hsp_xsum + (score*(kbp[H->hsp->context]->Lambda));
  736.                      Int4 new_sum = H_hsp_sum + (score - cutoff[index]);
  737.                      
  738.                      H->hsp_link.sum[index] = new_sum;
  739.                      H->hsp_link.num[index] = H_hsp_num+1;
  740.                      H->hsp_link.link[index] = H_hsp_link;
  741.                      lh_helper[H_index].sum[index] = new_sum;
  742.                      if (new_sum >= maxscore) 
  743.                      {
  744.                         maxscore=new_sum;
  745.                         best[index]=H;
  746.                      }
  747.                      H->hsp_link.xsum[index] = new_xsum;
  748.                      if(H_hsp_link)
  749.                         ((LinkHSPStruct*)H_hsp_link)->linked_to++;
  750.                   }
  751.                } /* end for H=... */
  752.             }
  753.             /****** loop iter for index = 1  **************************/
  754.             index=1;
  755.             maxscore = -cutoff[index];
  756.             H_index = 2;
  757.             for (H=hp_start->next; H!=NULL; H=H->next,H_index++) 
  758.             {
  759.                Int4 H_hsp_num=0;
  760.                Int4 H_hsp_sum=0;
  761.                double H_hsp_xsum=0.0;
  762.                LinkHSPStruct* H_hsp_link=NULL;
  763.                
  764.                H->hsp_link.changed=1;
  765.                H2 = H->hsp_link.link[index];
  766.                if ((!first_pass) && ((H2==0) || (H2->hsp_link.changed==0)))
  767.                {
  768.                   /* If the best choice last time has not been changed, then 
  769.                      it is still the best choice, so no need to walk down list.
  770.                   */
  771.                   if(H2){
  772.                      H_hsp_num=H2->hsp_link.num[index];
  773.                      H_hsp_sum=H2->hsp_link.sum[index];
  774.                      H_hsp_xsum=H2->hsp_link.xsum[index];
  775.                   }
  776.                   H_hsp_link=H2;
  777.                   H->hsp_link.changed=0;
  778.                } else if (H->hsp->score > cutoff[index]) {
  779.                   Int4 H_query_etrim = H->q_end_trim;
  780.                   Int4 H_sub_etrim = H->s_end_trim;
  781.                   
  782.                   /* Here we look at what was the best choice last time, if it's
  783.                    * still around, and set this to the initial choice. By
  784.                    * setting the best score to a (potentially) large value
  785.                    * initially, we can reduce the number of hsps checked. 
  786.                    */
  787.                   
  788.                   /* Currently we set the best score to a value just less than
  789.                    * the real value. This is not really necessary, but doing
  790.                    * this ensures that in the case of a tie, we make the same
  791.                    * selection the original code did.
  792.                    */
  793.                   
  794.                   if(!first_pass&&H2&&H2->linked_to>=0){
  795.                      if(1){
  796.                         /* We set this to less than the real value to keep the
  797.                            original ordering in case of ties. */
  798.                         H_hsp_sum=H2->hsp_link.sum[index]-1;
  799.                      }else{
  800.                         H_hsp_num=H2->hsp_link.num[index];
  801.                         H_hsp_sum=H2->hsp_link.sum[index];
  802.                         H_hsp_xsum=H2->hsp_link.xsum[index];
  803.                         H_hsp_link=H2;
  804.                      }
  805.                   }
  806.                   
  807.                   /* We now only walk down hits with the same frame sign */
  808.                   /* for (H2=H->prev; H2!=NULL; H2=H2->prev,H2_index--) */
  809.                   for (H2_index=H_index-1; H2_index>1;)
  810.                   {
  811.                      Int4 b0,b1,b2;
  812.                      Int4 q_off_t,s_off_t,sum,next_larger;
  813.                      LinkHelpStruct * H2_helper=&lh_helper[H2_index];
  814.                      sum = H2_helper->sum[index];
  815.                      next_larger = H2_helper->next_larger;
  816.                      
  817.                      s_off_t = H2_helper->s_off_trim;
  818.                      q_off_t = H2_helper->q_off_trim;
  819.                      
  820.                      b0 = sum <= H_hsp_sum;
  821.                      
  822.                      /* Compute the next H2_index */
  823.                      H2_index--;
  824.                      if(b0){  /* If this sum is too small to beat H_hsp_sum, advance to a larger sum */
  825.                         H2_index=next_larger;
  826.                      }
  827.                      /* combine tests to reduce mispredicts -cfj */
  828.                      b1 = q_off_t <= H_query_etrim;
  829.                      b2 = s_off_t <= H_sub_etrim;
  830.                      
  831.                      if(0) if(H2_helper->maxsum1<=H_hsp_sum)break;
  832.                      
  833.                      if (!(b0|b1|b2) )
  834.                      {
  835.                         H2 = H2_helper->ptr;
  836.                         
  837.                         H_hsp_num=H2->hsp_link.num[index];
  838.                         H_hsp_sum=H2->hsp_link.sum[index];
  839.                         H_hsp_xsum=H2->hsp_link.xsum[index];
  840.                         H_hsp_link=H2;
  841.                      }
  842.                   } /* end for H2_index... */
  843.                } /* end if(H->score>cuttof[]) */
  844.                { 
  845.                   Int4 score=H->hsp->score;
  846.                   double new_xsum = 
  847.                      H_hsp_xsum + (score*(kbp[H->hsp->context]->Lambda));
  848.                   Int4 new_sum = H_hsp_sum + (score - cutoff[index]);
  849.                   
  850.                   H->hsp_link.sum[index] = new_sum;
  851.                   H->hsp_link.num[index] = H_hsp_num+1;
  852.                   H->hsp_link.link[index] = H_hsp_link;
  853.                   lh_helper[H_index].sum[index] = new_sum;
  854.                   lh_helper[H_index].maxsum1 = MAX(lh_helper[H_index-1].maxsum1, new_sum);
  855.                   /* Update this entry's 'next_larger' field */
  856.                   {
  857.                      Int4 cur_sum=lh_helper[H_index].sum[1];
  858.                      Int4 prev = H_index-1;
  859.                      Int4 prev_sum = lh_helper[prev].sum[1];
  860.                      while((cur_sum>=prev_sum) && (prev>0)){
  861.                         prev=lh_helper[prev].next_larger;
  862.                         prev_sum = lh_helper[prev].sum[1];
  863.                      }
  864.                      lh_helper[H_index].next_larger = prev;
  865.                   }
  866.                   
  867.                   if (new_sum >= maxscore) 
  868.                   {
  869.                      maxscore=new_sum;
  870.                      best[index]=H;
  871.                   }
  872.                   H->hsp_link.xsum[index] = new_xsum;
  873.                   if(H_hsp_link)
  874.                      ((LinkHSPStruct*)H_hsp_link)->linked_to++;
  875.                }
  876.             }
  877.             path_changed=0;
  878.             first_pass=0;
  879.          }
  880.          /********************************/
  881.          if (!ignore_small_gaps)
  882.          {
  883.             /* Select the best ordering method.
  884.                First we add back in the value cutoff[index] * the number
  885.                of links, as this was subtracted out for purposes of the
  886.                comparison above. */
  887.             best[0]->hsp_link.sum[0] +=
  888.                (best[0]->hsp_link.num[0])*cutoff[0];
  889.             prob[0] = BLAST_SmallGapSumE(kbp[query_context],
  890.                          gap_size,
  891.                          best[0]->hsp_link.num[0], best[0]->hsp_link.xsum[0],
  892.                          query_length, subject_length,
  893.                          BLAST_GapDecayDivisor(gap_decay_rate,
  894.                                               best[0]->hsp_link.num[0]) );
  895.             /* Adjust the e-value because we are performing multiple tests */
  896.             if( best[0]->hsp_link.num[0] > 1 ) {
  897.               if( gap_prob == 0 || (prob[0] /= gap_prob) > INT4_MAX ) {
  898.                 prob[0] = INT4_MAX;
  899.               }
  900.             }
  901.             prob[1] = BLAST_LargeGapSumE(kbp[query_context],
  902.                          best[1]->hsp_link.num[1],
  903.                          best[1]->hsp_link.xsum[1],
  904.                          query_length, subject_length,
  905.                          BLAST_GapDecayDivisor(gap_decay_rate,
  906.                                               best[1]->hsp_link.num[1]));
  907.             if( best[1]->hsp_link.num[1] > 1 ) {
  908.               if( 1 - gap_prob == 0 || (prob[1] /= 1 - gap_prob) > INT4_MAX ) {
  909.                 prob[1] = INT4_MAX;
  910.               }
  911.             }
  912.             ordering_method =
  913.                prob[0]<=prob[1] ? BLAST_SMALL_GAPS : BLAST_LARGE_GAPS;
  914.          }
  915.          else
  916.          {
  917.             /* We only consider the case of big gaps. */
  918.             best[1]->hsp_link.sum[1] +=
  919.                (best[1]->hsp_link.num[1])*cutoff[1];
  920.             prob[1] = BLAST_LargeGapSumE(kbp[query_context],
  921.                          best[1]->hsp_link.num[1],
  922.                          best[1]->hsp_link.xsum[1],
  923.                          query_length, subject_length,
  924.                          BLAST_GapDecayDivisor(gap_decay_rate,
  925.                                               best[1]->hsp_link.num[1]));
  926.             ordering_method = BLAST_LARGE_GAPS;
  927.          }
  928.          best[ordering_method]->start_of_chain = TRUE;
  929.          
  930.          /* AM: Support for query concatenation. */
  931.          prob[ordering_method] *= 
  932.             ((double)query_info->eff_searchsp_array[query_context] /
  933.              ((double)subject_length*query_length));
  934.          
  935.          best[ordering_method]->hsp->evalue = prob[ordering_method];
  936.          
  937.          /* remove the links that have been ordered already. */
  938.          if (best[ordering_method]->hsp_link.link[ordering_method])
  939.             linked_set = TRUE;
  940.          else
  941.             linked_set = FALSE;
  942.          if (best[ordering_method]->linked_to>0) path_changed=1;
  943.          for (H=best[ordering_method]; H!=NULL;
  944.               H=H->hsp_link.link[ordering_method]) 
  945.          {
  946.             if (H->linked_to>1) path_changed=1;
  947.             H->linked_to=-1000;
  948.             H->hsp_link.changed=1;
  949.             /* record whether this is part of a linked set. */
  950.             H->linked_set = linked_set;
  951.             H->ordering_method = ordering_method;
  952.             H->hsp->evalue = prob[ordering_method];
  953.             if (H->next)
  954.                (H->next)->prev=H->prev;
  955.             if (H->prev)
  956.                (H->prev)->next=H->next;
  957.             number_of_hsps--;
  958.          }
  959.          
  960.       } /* end while num_hsps... */
  961. } /* end for frame_index ... */
  962.    sfree(hp_frame_start);
  963.    sfree(hp_frame_number);
  964.    sfree(hp_start->hsp);
  965.    sfree(hp_start);
  966.    if (translated_query) {
  967.       qsort(link_hsp_array,total_number_of_hsps,sizeof(LinkHSPStruct*), 
  968.             rev_compare_hsps_transl);
  969.       qsort(link_hsp_array, total_number_of_hsps,sizeof(LinkHSPStruct*), 
  970.             fwd_compare_hsps_transl);
  971.    } else {
  972.       qsort(link_hsp_array,total_number_of_hsps,sizeof(LinkHSPStruct*), 
  973.             rev_compare_hsps);
  974.       qsort(link_hsp_array, total_number_of_hsps,sizeof(LinkHSPStruct*), 
  975.             fwd_compare_hsps);
  976.    }
  977.    /* Sort by starting position. */
  978.    
  979. for (index=0, last_hsp=NULL;index<total_number_of_hsps; index++) 
  980. {
  981. H = link_hsp_array[index];
  982. H->prev = NULL;
  983. H->next = NULL;
  984. }
  985.    /* hook up the HSP's. */
  986. first_hsp = NULL;
  987. for (index=0, last_hsp=NULL;index<total_number_of_hsps; index++) 
  988.    {
  989. H = link_hsp_array[index];
  990.       /* If this is not a single piece or the start of a chain, then Skip it. */
  991.       if (H->linked_set == TRUE && H->start_of_chain == FALSE)
  992. continue;
  993.       /* If the HSP has no "link" connect the "next", otherwise follow the "link"
  994.          chain down, connecting them with "next" and "prev". */
  995. if (last_hsp == NULL)
  996. first_hsp = H;
  997. H->prev = last_hsp;
  998. ordering_method = H->ordering_method;
  999. if (H->hsp_link.link[ordering_method] == NULL)
  1000. {
  1001.          /* Grab the next HSP that is not part of a chain or the start of a chain */
  1002.          /* The "next" pointers are not hooked up yet in HSP's further down array. */
  1003.          index1=index;
  1004.          H2 = index1<(total_number_of_hsps-1) ? link_hsp_array[index1+1] : NULL;
  1005.          while (H2 && H2->linked_set == TRUE && 
  1006.                 H2->start_of_chain == FALSE)
  1007.          {
  1008.             index1++;
  1009.       H2 = index1<(total_number_of_hsps-1) ? link_hsp_array[index1+1] : NULL;
  1010.          }
  1011.          H->next= H2;
  1012. }
  1013. else
  1014. {
  1015. /* The first one has the number of links correct. */
  1016. num_links = H->hsp_link.num[ordering_method];
  1017. link = H->hsp_link.link[ordering_method];
  1018. while (link)
  1019. {
  1020. H->hsp->num = num_links;
  1021. H->sumscore = H->hsp_link.sum[ordering_method];
  1022. H->next = (LinkHSPStruct*) link;
  1023. H->prev = last_hsp;
  1024. last_hsp = H;
  1025. H = H->next;
  1026. if (H != NULL)
  1027.     link = H->hsp_link.link[ordering_method];
  1028. else
  1029.     break;
  1030. }
  1031. /* Set these for last link in chain. */
  1032. H->hsp->num = num_links;
  1033. H->sumscore = H->hsp_link.sum[ordering_method];
  1034.          /* Grab the next HSP that is not part of a chain or the start of a chain */
  1035.          index1=index;
  1036.          H2 = index1<(total_number_of_hsps-1) ? link_hsp_array[index1+1] : NULL;
  1037.          while (H2 && H2->linked_set == TRUE && 
  1038.                 H2->start_of_chain == FALSE)
  1039.    {
  1040.             index1++;
  1041.             H2 = index1<(total_number_of_hsps-1) ? link_hsp_array[index1+1] : NULL;
  1042. }
  1043.          H->next= H2;
  1044. H->prev = last_hsp;
  1045. }
  1046. last_hsp = H;
  1047. }
  1048.    /* The HSP's may be in a different order than they were before, 
  1049.       but first_hsp contains the first one. */
  1050.    for (index = 0, H = first_hsp; index < hsp_list->hspcnt; index++) {
  1051.       hsp_list->hsp_array[index] = H->hsp;
  1052.       /* Free the wrapper structure */
  1053.       H2 = H->next;
  1054.       sfree(H);
  1055.       H = H2;
  1056.    }
  1057.    sfree(link_hsp_array);
  1058.    sfree(lh_helper);
  1059.    return 0;
  1060. }
  1061. static void ConnectLinkHSPStructs(LinkHSPStruct** linkhsp_array, Int4 hspcnt,
  1062.                                   Uint1* subject_seq)
  1063. {
  1064.    Int4 index, index1, i;
  1065.    LinkHSPStruct* hsp;
  1066.    qsort(linkhsp_array, hspcnt, sizeof(LinkHSPStruct*), 
  1067.          sumscore_compare_hsps);
  1068.    hsp = linkhsp_array[0];
  1069.    for (index=0; index<hspcnt; hsp = hsp->next) {
  1070.       if (hsp->linked_set) {
  1071.          index1 = hsp->hsp->num;
  1072.          for (i=1; i < index1; i++, hsp = hsp->next) {
  1073.             hsp->next->hsp->evalue = hsp->hsp->evalue; 
  1074.             hsp->next->hsp->num = hsp->hsp->num;
  1075.             hsp->next->sumscore = hsp->sumscore;
  1076.             if (FindSpliceJunction(subject_seq, hsp->hsp, hsp->next->hsp)) {
  1077.                /* Kludge: ordering_method here would indicate existence of
  1078.                   splice junctions(s) */
  1079.                hsp->hsp->splice_junction++;
  1080.                hsp->next->hsp->splice_junction++;
  1081.             } else {
  1082.                hsp->hsp->splice_junction--;
  1083.                hsp->next->hsp->splice_junction--;
  1084.             }
  1085.          }
  1086.       } 
  1087.       while (++index < hspcnt)
  1088.          if (!linkhsp_array[index]->linked_set ||
  1089.              linkhsp_array[index]->start_of_chain)
  1090.             break;
  1091.       if (index == hspcnt) {
  1092.          hsp->next = NULL;
  1093.          break;
  1094.       }
  1095.       hsp->next = linkhsp_array[index];
  1096.    }
  1097. }
  1098. static Int2
  1099. new_link_hsps(Uint1 program_number, BlastHSPList* hsp_list, 
  1100.    BlastQueryInfo* query_info, BLAST_SequenceBlk* subject,
  1101.    BlastScoreBlk* sbp, const BlastHitSavingParameters* hit_params)
  1102. {
  1103.    BlastHSP** hsp_array;
  1104.    LinkHSPStruct** score_hsp_array,** offset_hsp_array,** end_hsp_array;
  1105.    LinkHSPStruct* hsp,* head_hsp,* best_hsp,* var_hsp;
  1106.    Int4 hspcnt, index, index1, i;
  1107.    double best_evalue, evalue;
  1108.    Int4 sumscore, best_sumscore = 0;
  1109.    Boolean reverse_link;
  1110.    Int4 longest_intron = hit_params->options->longest_intron;
  1111.    LinkHSPStruct** link_hsp_array;
  1112.    hspcnt = hsp_list->hspcnt;
  1113.    hsp_array = hsp_list->hsp_array;
  1114.    link_hsp_array = (LinkHSPStruct**) malloc(hspcnt*sizeof(LinkHSPStruct*));
  1115.    for (index = 0; index < hspcnt; ++index) {
  1116.       link_hsp_array[index] = (LinkHSPStruct*) calloc(1, sizeof(LinkHSPStruct));
  1117.       link_hsp_array[index]->hsp = hsp_array[index];
  1118.       link_hsp_array[index]->linked_set = FALSE;
  1119.       hsp_array[index]->num = 1;
  1120.       hsp_array[index]->splice_junction = FALSE;
  1121.    }
  1122.    score_hsp_array = (LinkHSPStruct**) malloc(hspcnt*sizeof(LinkHSPStruct*));
  1123.    offset_hsp_array = (LinkHSPStruct**) malloc(hspcnt*sizeof(LinkHSPStruct*));
  1124.    end_hsp_array = (LinkHSPStruct**) malloc(hspcnt*sizeof(LinkHSPStruct*));
  1125.    memcpy(score_hsp_array, link_hsp_array, hspcnt*sizeof(LinkHSPStruct*));
  1126.    memcpy(offset_hsp_array, link_hsp_array, hspcnt*sizeof(LinkHSPStruct*));
  1127.    memcpy(end_hsp_array, link_hsp_array, hspcnt*sizeof(LinkHSPStruct*));
  1128.    qsort(offset_hsp_array, hspcnt, sizeof(LinkHSPStruct*), fwd_compare_hsps);
  1129.    qsort(end_hsp_array, hspcnt, sizeof(LinkHSPStruct*), end_compare_hsps);
  1130.    qsort(score_hsp_array, hspcnt, sizeof(LinkHSPStruct*), 
  1131.             sumscore_compare_hsps);
  1132.       
  1133.    head_hsp = NULL;
  1134.    for (index = 0; index < hspcnt && score_hsp_array[index]; ) {
  1135.       if (!head_hsp) {
  1136.          while (index<hspcnt && score_hsp_array[index] && 
  1137.                 score_hsp_array[index]->linked_set)
  1138.             index++;
  1139.          if (index==hspcnt)
  1140.             break;
  1141.          head_hsp = score_hsp_array[index];
  1142.       }
  1143.       best_evalue = head_hsp->hsp->evalue;
  1144.       best_hsp = NULL;
  1145.       reverse_link = FALSE;
  1146.       
  1147.       if (head_hsp->linked_set)
  1148.          for (var_hsp = head_hsp, i=1; i<head_hsp->hsp->num; 
  1149.               var_hsp = var_hsp->next, i++);
  1150.       else
  1151.          var_hsp = head_hsp;
  1152.       index1 = hsp_binary_search(offset_hsp_array, hspcnt,
  1153.                                  var_hsp->hsp->query.end - WINDOW_SIZE, TRUE);
  1154.       while (index1 < hspcnt && offset_hsp_array[index1]->hsp->query.offset < 
  1155.              var_hsp->hsp->query.end + WINDOW_SIZE) {
  1156.          hsp = offset_hsp_array[index1++];
  1157.          /* If this is already part of a linked set, disregard it */
  1158.          if (hsp == var_hsp || hsp == head_hsp || 
  1159.              (hsp->linked_set && !hsp->start_of_chain))
  1160.             continue;
  1161.          /* Check if the subject coordinates are consistent with query */
  1162.          if ((hsp->hsp->subject.offset < 
  1163.              var_hsp->hsp->subject.end - WINDOW_SIZE) || 
  1164.              (hsp->hsp->subject.offset > 
  1165.               var_hsp->hsp->subject.end + longest_intron))
  1166.             continue;
  1167.          /* Check if the e-value for the combined two HSPs is better than for
  1168.             one of them */
  1169.          if ((evalue = SumHSPEvalue(program_number, sbp, query_info, subject, 
  1170.                                     hit_params, head_hsp, hsp, &sumscore)) < 
  1171.              MIN(best_evalue, hsp->hsp->evalue)) {
  1172.             best_hsp = hsp;
  1173.             best_evalue = evalue;
  1174.             best_sumscore = sumscore;
  1175.          }
  1176.       }
  1177.       index1 = hsp_binary_search(end_hsp_array, hspcnt,
  1178.                                  head_hsp->hsp->query.offset - WINDOW_SIZE, FALSE);
  1179.       while (index1 < hspcnt && end_hsp_array[index1]->hsp->query.end < 
  1180.              head_hsp->hsp->query.offset + WINDOW_SIZE) {
  1181.          hsp = end_hsp_array[index1++];
  1182.          /* Check if the subject coordinates are consistent with query */
  1183.          if (hsp == head_hsp || 
  1184.              hsp->hsp->subject.end > head_hsp->hsp->subject.offset + WINDOW_SIZE || 
  1185.              hsp->hsp->subject.end < head_hsp->hsp->subject.offset - longest_intron)
  1186.             continue;
  1187.          if (hsp->linked_set) {
  1188.             for (var_hsp = hsp, i=1; var_hsp->start_of_chain == FALSE; 
  1189.                  var_hsp = var_hsp->prev, i++);
  1190.             if (i<var_hsp->hsp->num || var_hsp == head_hsp)
  1191.                continue;
  1192.          } else
  1193.             var_hsp = hsp;
  1194.          /* Check if the e-value for the combined two HSPs is better than for
  1195.             one of them */
  1196.          if ((evalue = SumHSPEvalue(program_number, sbp, query_info, subject, 
  1197.                           hit_params, var_hsp, head_hsp, &sumscore)) < 
  1198.              MIN(var_hsp->hsp->evalue, best_evalue)) {
  1199.             best_hsp = hsp;
  1200.             best_evalue = evalue;
  1201.             best_sumscore = sumscore;
  1202.             reverse_link = TRUE;
  1203.          }
  1204.       }
  1205.          
  1206.       /* Link these HSPs together */
  1207.       if (best_hsp != NULL) {
  1208.          if (!reverse_link) {
  1209.             head_hsp->start_of_chain = TRUE;
  1210.             head_hsp->sumscore = best_sumscore;
  1211.             head_hsp->hsp->evalue = best_evalue;
  1212.             best_hsp->start_of_chain = FALSE;
  1213.             if (head_hsp->linked_set) 
  1214.                for (var_hsp = head_hsp, i=1; i<head_hsp->hsp->num; 
  1215.                     var_hsp = var_hsp->next, i++);
  1216.             else 
  1217.                var_hsp = head_hsp;
  1218.             var_hsp->next = best_hsp;
  1219.             best_hsp->prev = var_hsp;
  1220.             head_hsp->hsp->num += best_hsp->hsp->num;
  1221.          } else {
  1222.             best_hsp->next = head_hsp;
  1223.             head_hsp->prev = best_hsp;
  1224.             if (best_hsp->linked_set) {
  1225.                for (var_hsp = best_hsp; 
  1226.                     var_hsp->start_of_chain == FALSE; 
  1227.                     var_hsp = var_hsp->prev);
  1228.             } else
  1229.                   var_hsp = best_hsp;
  1230.             var_hsp->start_of_chain = TRUE;
  1231.             var_hsp->sumscore = best_sumscore;
  1232.             var_hsp->hsp->evalue = best_evalue;
  1233.             var_hsp->hsp->num += head_hsp->hsp->num;
  1234.             head_hsp->start_of_chain = FALSE;
  1235.          }
  1236.          
  1237.          head_hsp->linked_set = best_hsp->linked_set = TRUE;
  1238.          if (reverse_link)
  1239.             head_hsp = var_hsp;
  1240.       } else {
  1241.          head_hsp = NULL;
  1242.          index++;
  1243.       }
  1244.    }
  1245.   
  1246.    ConnectLinkHSPStructs(score_hsp_array, hspcnt, 
  1247.                          subject->sequence_start);
  1248.    head_hsp = score_hsp_array[0];
  1249.    sfree(score_hsp_array);
  1250.    sfree(offset_hsp_array);
  1251.    sfree(end_hsp_array);
  1252.    /* Place HSPs in the original HSP array in their new order */
  1253.    for (index=0; head_hsp && index<hspcnt; index++) {
  1254.       hsp_list->hsp_array[index] = head_hsp->hsp;
  1255.       var_hsp = head_hsp->next;
  1256.       sfree(head_hsp);
  1257.       head_hsp = var_hsp;
  1258.    }
  1259.    sfree(link_hsp_array);
  1260.    return 0;
  1261. }
  1262. Int2 
  1263. BLAST_LinkHsps(Uint1 program_number, BlastHSPList* hsp_list, 
  1264.    BlastQueryInfo* query_info, BLAST_SequenceBlk* subject, 
  1265.    BlastScoreBlk* sbp, const BlastHitSavingParameters* hit_params,
  1266.    Boolean gapped_calculation)
  1267. {
  1268. if (hsp_list && hsp_list->hspcnt > 0)
  1269. {
  1270.       /* Link up the HSP's for this hsp_list. */
  1271.       if (program_number != blast_type_tblastn ||
  1272.           hit_params->options->longest_intron <= 0)
  1273.       {
  1274.          link_hsps(program_number, hsp_list, query_info, subject, sbp, 
  1275.                    hit_params, gapped_calculation);
  1276.          /* The HSP's may be in a different order than they were before, 
  1277.             but hsp contains the first one. */
  1278.       } else {
  1279.          /* Calculate individual HSP e-values first - they'll be needed to
  1280.             compare with sum e-values. */
  1281.          Blast_HSPListGetEvalues(program_number, query_info, 
  1282.                                     hsp_list, gapped_calculation, sbp);
  1283.          
  1284.          new_link_hsps(program_number, hsp_list, query_info, subject, sbp, 
  1285.                        hit_params);
  1286.       }
  1287. }
  1288. return 0;
  1289. }