~ubuntu-branches/ubuntu/karmic/ncbi-tools6/karmic

« back to all changes in this revision

Viewing changes to tools/blastutl.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2006-10-22 19:32:02 UTC
  • mfrom: (1.2.1 upstream) (2.1.4 dapper)
  • Revision ID: james.westby@ubuntu.com-20061022193202-6svrvb6l52n0uhe4
Tags: 6.1.20061015-1
* New upstream release.
* Don't bother linking against indirectly used system libraries.
* Update man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
static char const rcsid[] = "$Id: blastutl.c,v 6.447 2004/10/18 13:02:41 madden Exp $";
 
1
static char const rcsid[] = "$Id: blastutl.c,v 6.466 2006/08/10 17:34:38 merezhuk Exp $";
2
2
 
3
3
/* ===========================================================================
4
4
*
32
32
 
33
33
Contents: Utilities for BLAST
34
34
 
35
 
$Revision: 6.447 $
 
35
$Revision: 6.466 $
36
36
 
37
37
******************************************************************************/
38
38
/*
39
39
 *
40
40
* $Log: blastutl.c,v $
 
41
* Revision 6.466  2006/08/10 17:34:38  merezhuk
 
42
* Fix for reading -z advanced option by StringToInt8; RT # 15187990
 
43
*
 
44
* Revision 6.465  2006/02/15 18:23:47  madden
 
45
* Made changes so that CheckStartForGappedAlignment by default
 
46
* checks ungapped alignments of length 11, rather than length 10.
 
47
* Made changes to the rules used when the starting point is close to
 
48
* the edge of the preliminary gapped alignment.
 
49
* (from Mike Gertz)
 
50
*
 
51
* Revision 6.464  2005/12/01 15:10:23  madden
 
52
* Gave BLASTCheckHSPInclusion external linkage (i.e. removed the static specifier).
 
53
*
 
54
* Revision 6.463  2005/10/13 15:59:06  camacho
 
55
* Add code to fix cutoff scores in PSI-BLAST.
 
56
*
 
57
* Revision 6.462  2005/07/28 14:57:09  coulouri
 
58
* remove dead code
 
59
*
 
60
* Revision 6.461  2005/07/27 15:51:54  coulouri
 
61
* remove unused queue_callback
 
62
*
 
63
* Revision 6.460  2005/05/02 16:03:14  coulouri
 
64
* refactor code to set db_chunk_size
 
65
*
 
66
* Revision 6.459  2005/04/25 14:16:36  coulouri
 
67
* set db_chunk_size adaptively
 
68
*
 
69
* Revision 6.458  2005/04/04 20:44:27  camacho
 
70
* Do not overwrite the effective search space in Pssm2Sequences if specified in the options structure
 
71
*
 
72
* Revision 6.457  2005/02/07 15:30:08  dondosha
 
73
* Removed restriction on the value of longest intron option
 
74
*
 
75
* Revision 6.456  2005/01/24 20:37:37  camacho
 
76
* Added conditional compilation to structs need for BLAST_CLUSTER_HITS
 
77
*
 
78
* Revision 6.455  2005/01/18 14:54:13  camacho
 
79
* Change in tie-breakers for score comparison, suggestion by Mike Gertz
 
80
*
 
81
* Revision 6.454  2004/12/20 15:22:16  camacho
 
82
* Calculate kbp_ideal values rather than loading them from pre-computed values
 
83
*
 
84
* Revision 6.453  2004/12/01 17:24:15  coulouri
 
85
* do not dereference null pointer
 
86
*
 
87
* Revision 6.452  2004/11/22 16:10:11  dondosha
 
88
* Minor fix to make sure that "evalue" score type is always used when hsp is not part of a linked set
 
89
*
 
90
* Revision 6.451  2004/11/04 15:51:55  bealer
 
91
* - bl2seq should use dblen as average length if database is not available.
 
92
*
 
93
* Revision 6.450  2004/11/01 14:07:56  madden
 
94
* From Mike Gertz:
 
95
*
 
96
*    - In query_offset_compare_hsp and query_end_compare_hsp, use the
 
97
*      subject query/offset as a tie-breaker.  Without this tie-breaker
 
98
*      CheckGappedAlignmentsForOverlap won't work properly.
 
99
*
 
100
*    - In CheckGappedAlignmentsForOverlap check that hsp_array, rather
 
101
*      than *hsp_array, is not nil.
 
102
*
 
103
*    - In BlastSaveCurrentHsp, rewrote the binary search to use
 
104
*      score_compare_hsps, so that the answers are consistent with the
 
105
*      heap code used in the algo/blast/core code.
 
106
*
 
107
*    - In BlastGappedScoreInternal delete gapped extensions that don't
 
108
*      reach the cutoff score (cutoff_s1).
 
109
*
 
110
* Revision 6.449  2004/10/25 18:36:17  papadopo
 
111
* From Michael Gertz: remove unneeded decrement of alignment offsets in BlastNtSaveCurrentHsp
 
112
*
 
113
* Revision 6.448  2004/10/19 19:42:17  dondosha
 
114
* Optimized algorithm in BlastPruneSeqAlignByGiList to make it up to 25 times faster; Added new function BlastPruneSeqAlignBySortedGiList
 
115
*
41
116
* Revision 6.447  2004/10/18 13:02:41  madden
42
117
* Changes from Mike Gertz:
43
118
*         - In score_compare_hsps, query_offset_compare_hsp and
1754
1829
#include <simutil.h>
1755
1830
#include <blfmtutl.h>
1756
1831
 
1757
 
 
1758
1832
typedef struct _pgp_blast_options {
1759
1833
    BLAST_OptionsBlkPtr options;
1760
1834
    CharPtr blast_database;
2939
3013
{
2940
3014
    BLAST_ScorePtr *retval = NULL;
2941
3015
    posSearchItems *posSearch = NULL;
2942
 
    Int4 qlen, alphabet_sz, rv, array_sz;
 
3016
    Int4 qlen, alphabet_sz, rv;
2943
3017
    Nlm_FloatHi scalingFactor = search->pbp->scalingFactor;
2944
3018
    BLAST_ScoreBlkPtr sbp = NULL;
2945
3019
    ValNodePtr error_return;
2946
 
    Int4Ptr open, extend;        /* gap open and extension costs */
2947
 
    Nlm_FloatHiPtr lambda, K, H; /* Karlin_Altschul score paramters */
2948
3020
    Int4 i, gap_open, gap_extend;
2949
3021
 
2950
3022
    if (!search || !compactSearch || !posFreqs)
2995
3067
        return NULL;
2996
3068
    }
2997
3069
 
2998
 
    array_sz = BlastKarlinGetMatrixValues(sbp->name, &open, &extend, &lambda,
2999
 
            &K, &H, NULL);
3000
 
    if (array_sz > 0) {
3001
 
        for (i = 0; i < array_sz; i++) {
3002
 
            if (open[i] == INT2_MAX && extend[i] == INT2_MAX) {
3003
 
                sbp->kbp_ideal = BlastKarlinBlkCreate();
3004
 
                sbp->kbp_ideal->Lambda = lambda[i];
3005
 
                sbp->kbp_ideal->K = K[i];
3006
 
                sbp->kbp_ideal->H = H[i];
3007
 
            }
3008
 
        }
3009
 
        MemFree(open); MemFree(extend); 
3010
 
        MemFree(lambda); MemFree(K); MemFree(H);
3011
 
    }
3012
3070
    if (sbp->kbp_ideal == NULL)
3013
3071
        sbp->kbp_ideal = BlastKarlinBlkStandardCalcEx(sbp);
3014
3072
    compactSearch->lambda =  sbp->kbp_gap_std[0]->Lambda;
3407
3465
                        options->db_length : SeqLocLen(pssm_slp);
3408
3466
        Int4 nseqs = (options->dbseq_num != 0) ?  options->dbseq_num : 1;
3409
3467
 
3410
 
        search->searchsp_eff  = BLASTCalculateSearchSpace(options, nseqs, 
3411
 
                dblen, SeqLocLen(target_seqs[i]));
 
3468
        /* If search space has been specified in the options structure, the it
 
3469
         * must have been set in BLASTSetUpSearchEx, so don't overwrite it */
 
3470
        if ( ! (options->searchsp_eff > 0) ) {
 
3471
            search->searchsp_eff  = BLASTCalculateSearchSpace(options, nseqs, 
 
3472
                    dblen, SeqLocLen(target_seqs[i]));
 
3473
        }
3412
3474
        sa_array[i] = B2SPssmOnTheFlyByLoc(search, target_seqs[i]);
3413
3475
    }
3414
3476
 
3464
3526
        /* If filtering is performed, do not reverse the sequence.  
3465
3527
           In this case the wrong sequence would be filtered. */
3466
3528
        reverse_forbidden = FALSE;
3467
 
        if (options && ((options->filter_string &&
 
3529
        if ((options && ((options->filter_string &&
3468
3530
                        StringCmp(options->filter_string, "F")) ||
3469
 
                        options->is_megablast_search) ||
 
3531
                        options->is_megablast_search)) ||
3470
3532
                        matrix != NULL)
3471
3533
        {
3472
3534
                reverse_forbidden = TRUE;
3620
3682
 
3621
3683
        seqalign = BlastTwoSequencesCore(search, subject_slp, subject_seq, subject_length, reverse);
3622
3684
 
3623
 
#if 0
3624
 
    /* This is turned off for right now */
3625
 
    if (options->tweak_parameters || options->smith_waterman) {
3626
 
        Boolean free_subject_info = FALSE;
3627
 
 
3628
 
        if (search->subject_info == NULL) {
3629
 
            search->subject_info = BLASTSubjectInfoNew(
3630
 
                    SeqIdSetDup(SeqLocId(subject_slp)), NULL, subject_length);
3631
 
            free_subject_info = TRUE;
3632
 
        }
3633
 
 
3634
 
        /* Use composition-based statistics */
3635
 
        seqalign = RedoAlignmentCore(search, options, 
3636
 
                search->result_struct->hitlist_count,
3637
 
                options->tweak_parameters, options->smith_waterman);
3638
 
        for (index = 0; index<search->result_struct->hitlist_count; index++)
3639
 
            BLASTResultFreeHsp(search->result_struct->results[index]);
3640
 
        for (index = 0; index<search->result_struct->hitlist_count; index++)
3641
 
            SeqAlignSetFree(search->result_struct->results[index]->seqalign);
3642
 
 
3643
 
        if (free_subject_info)
3644
 
            search->subject_info =
3645
 
                BLASTSubjectInfoDestruct(search->subject_info);
3646
 
    }
3647
 
#endif
3648
 
 
3649
3685
        if (complement)
3650
3686
        {
3651
3687
                seqalign = SeqAlignListReverseStrand(seqalign);
3965
4001
        register int state;
3966
4002
        Int2 total_remainder;
3967
4003
        Int4 prot_length;
3968
 
        register int byte_value, codon;
 
4004
        register int byte_value, codon=0;
3969
4005
        Uint1 last_remainder, last_byte, remainder;
3970
4006
        register Uint1Ptr translation, nt_seq_end, nt_seq_start;
3971
4007
        Uint1Ptr prot_seq_start;
4413
4449
    return 0;
4414
4450
}
4415
4451
 
 
4452
/* Code in BLAST_CLUSTER_HITS is not currently in use */
 
4453
 
 
4454
#ifdef BLAST_CLUSTER_HITS        
4416
4455
typedef struct _blast_result_with_subject_id {
4417
4456
   BLASTResultHspPtr hsp;
4418
4457
   Int4 hitlist_index, hsp_index;
4450
4489
   else /* Should never happen */
4451
4490
      return 0;
4452
4491
}
 
4492
#endif
4453
4493
 
4454
4494
#define CLUSTER_LENGTH_THRESH 0.1
4455
4495
#define CLUSTER_OVERLAP_THRESH 0.9
4456
4496
#define CLUSTER_SCORE_THRESH 1.6
4457
4497
 
 
4498
Nlm_FloatHi s_ComputeAverageLength(const BlastSearchBlk* search)
 
4499
{
 
4500
    Nlm_FloatHi retval = 0.0;
 
4501
 
 
4502
        if (StringCmp(search->prog_name, "blastn") != 0) {
 
4503
                retval = BLAST_AA_AVGLEN;
 
4504
        } else {
 
4505
                retval = BLAST_NT_AVGLEN;
 
4506
        }
 
4507
 
 
4508
    if (search->rdfp) {
 
4509
                Int4 total_number = 0;
 
4510
                Int8 total_length = 0;
 
4511
 
 
4512
                readdb_get_totals(search->rdfp, &total_length, &total_number);
 
4513
                if (total_number > 0)
 
4514
                        retval = total_length/total_number;
 
4515
    } else if (search->dblen > 0 && search->dbseq_num == 1) {
 
4516
        retval = search->dblen;
 
4517
    }
 
4518
 
 
4519
    return retval;
 
4520
}
 
4521
 
4458
4522
SeqAlignPtr LIBCALL
4459
4523
BioseqBlastEngineCore(BlastSearchBlkPtr search, BLAST_OptionsBlkPtr options,
4460
4524
                        Int4Ptr *pos_matrix)
4461
4525
{
4462
 
        BLASTResultHspPtr hsp, hsp1;
4463
 
        BlastResultHspWithIdPtr PNTR hspp;
4464
 
        BLASTResultsStructPtr result_struct;
4465
 
        BLASTResultHitlistPtr   result_hitlist;
4466
 
        Char buffer[512];
4467
 
        GapXEditBlockPtr edit_block;
4468
 
        Int4 hitlist_count, hitlist_max, hspcnt, index, index1, index2;
4469
 
        Int4 length, sequence_length;
4470
 
        Int4 q_overlap, total_num_hsp=0;
4471
 
        SeqAlignPtr sap, head, seqalign, seqalign_var;
4472
 
        SeqIdPtr gi_list=NULL, subject_id;
4473
 
        Uint1Ptr sequence;
4474
 
        StdSegPtr ssp;
4475
 
        BioseqPtr bsp1, bsp2, PNTR bspp; 
4476
 
        BlastSearchBlkPtr search1;
 
4526
        Int4 hitlist_max;
 
4527
        SeqAlignPtr head, seqalign;
 
4528
#ifdef BLAST_CLUSTER_HITS
 
4529
        BLASTResultHspPtr hsp, hsp1;
 
4530
        BlastResultHspWithIdPtr PNTR hspp;
 
4531
        BLASTResultsStructPtr result_struct;
 
4532
        BLASTResultHitlistPtr   result_hitlist;
 
4533
        Int4 hspcnt, index, index1, index2;
 
4534
        Int4 q_overlap;
 
4535
        BioseqPtr bsp1, bsp2, PNTR bspp;
 
4536
        BlastSearchBlkPtr search1;
4477
4537
        BLAST_KarlinBlkPtr kbp;
4478
4538
        FloatHi bit_score;
4479
 
 
 
4539
#endif
4480
4540
 
4481
4541
        head = seqalign = NULL;
4482
4542
 
4483
4543
        if (search == NULL || search->query_invalid)
4484
4544
                return NULL;
4485
4545
 
4486
 
 
4487
4546
        /* If pos_matrix is not NULL, then psi-blast iterations are being 
4488
4547
        performed.  The first psi-blast iteration should be with normal
4489
4548
        blast. */
4508
4567
                       search->wfp_second = BLAST_WordFinderNew(search->sbp->alphabet_size,options->wordsize,1, FALSE);
4509
4568
                }
4510
4569
 
 
4570
 
4511
4571
                /* Only find words once if thresholds are the same. */
4512
4572
                 search->wfp = search->wfp_first;
4513
4573
                 if (search->whole_query == TRUE)
4516
4576
                        BlastNewFindWords(search, search->required_start, search->required_end, search->pbp->threshold_second, (Uint1) 0);
4517
4577
                 lookup_position_aux_destruct(search->wfp->lookup);
4518
4578
                 search->wfp_second = search->wfp_first;
 
4579
 
 
4580
#if 0
 
4581
            /* recalculate the cutoff scores with the newly calculated
 
4582
               Karlin-Altschul parameters. */
 
4583
            blast_set_parameters(search, 
 
4584
                                 options->dropoff_1st_pass,
 
4585
                                 options->dropoff_2nd_pass,
 
4586
                                 s_ComputeAverageLength(search),
 
4587
                                 search->searchsp_eff,
 
4588
                                 options->window_size);
 
4589
              /* ... and make sure that the appropriate cutoff is used in the
 
4590
               * word finder */
 
4591
            search->pbp->cutoff_s2_set = TRUE;
 
4592
#endif
4519
4593
        }
4520
4594
 
4521
4595
        /* Starting awake thread if multithreaded. */
5104
5178
 
5105
5179
{
5106
5180
        Boolean make_seqloc, start=TRUE;
5107
 
        Int4 index, total, start_pos, stop_pos, largest_stop_pos;
 
5181
        Int4 index, total, start_pos=0, stop_pos, largest_stop_pos=0;
5108
5182
        SeqIntPtr sint;
5109
5183
        SeqLocPtr retval=NULL;
5110
5184
 
5681
5755
    BlastThrInfoPtr thr_info;
5682
5756
    
5683
5757
    thr_info = MemNew(sizeof(BlastThrInfo));
5684
 
    thr_info->db_chunk_size = BLAST_DB_CHUNK_SIZE;
5685
5758
    
5686
5759
    return thr_info;
5687
5760
}
5821
5894
            new_search->query_dnap = BlastMakeCopyQueryDNAP(search->query_dnap);
5822
5895
 
5823
5896
        new_search->thr_info = search->thr_info;
5824
 
        new_search->queue_callback = search->queue_callback;
5825
5897
        new_search->semid = search->semid;
5826
5898
        
5827
5899
#ifdef BLAST_COLLECT_STATS
6675
6747
        Boolean mask_state;
6676
6748
        Char cmd_buf[2*PATH_MAX], temp_file[PATH_MAX];
6677
6749
        CharPtr filter_dir;
6678
 
        Int4 index, mask_begin;
 
6750
        Int4 index, mask_begin=0;
6679
6751
        SeqEntryPtr sep;
6680
6752
        SeqLocPtr slp_mask;
6681
6753
        SeqPortPtr spp_filter, spp_unfilter;
6958
7030
        /* -z Effective database length */
6959
7031
        index = BlastGetLetterIndex(opt_str, 'z');
6960
7032
        if (values[index] != NULL) {
6961
 
           const char **dummy;
6962
 
           options->db_length =  StringToInt8(values[index], dummy);
 
7033
           const char *dummy=NULL;
 
7034
           options->db_length =  StringToInt8(values[index], &dummy);
6963
7035
        }
6964
7036
 
6965
7037
        /* -c Constant in pseudocounts for multipass version */
7010
7082
           if (options->is_megablast_search)
7011
7083
              options->mb_template_length = atoi(values[index]);
7012
7084
           else 
7013
 
              options->longest_intron = 
7014
 
                 MAX(atoi(values[index]), MAX_INTRON_LENGTH);
 
7085
              options->longest_intron = atoi(values[index]);
7015
7086
        }
7016
7087
 
7017
7088
        /* -g  Scan every base of the database for megablast */
7634
7705
 
7635
7706
BLAST_HSPPtr BLAST_HSPFree(BLAST_HSPPtr hsp)
7636
7707
{
 
7708
if (hsp)
7637
7709
   hsp->gap_info = GapXEditBlockDelete(hsp->gap_info);
7638
 
   return (BLAST_HSPPtr) MemFree(hsp);
 
7710
 
 
7711
return (BLAST_HSPPtr) MemFree(hsp);
7639
7712
}
7640
7713
 
7641
7714
/* 
7836
7909
score_compare_hsps(VoidPtr v1, VoidPtr v2)
7837
7910
 
7838
7911
{
7839
 
    BLAST_HSPPtr h1, h2;
7840
 
    BLAST_HSPPtr PNTR hp1, PNTR hp2;
7841
 
 
7842
 
    hp1 = (BLAST_HSPPtr PNTR) v1;
7843
 
    hp2 = (BLAST_HSPPtr PNTR) v2;
7844
 
    h1 = *hp1;
7845
 
    h2 = *hp2;
7846
 
 
7847
 
    if (h1 == NULL) {
7848
 
        return (h2 == NULL) ? 0 : 1;
7849
 
    } else if (h2 == NULL) {
7850
 
      return -1;
 
7912
    BLAST_HSPPtr hsp1, hsp2;    /* the HSPs to be compared */
 
7913
    int result = 0;             /* the result of the comparison */
 
7914
 
 
7915
    hsp1 = *((BLAST_HSPPtr PNTR) v1);
 
7916
    hsp2 = *((BLAST_HSPPtr PNTR) v2);
 
7917
 
 
7918
    /* Null HSPs are "greater" than any non-null ones, so they go to the end
 
7919
       of a sorted list. */
 
7920
    if (!hsp1 && !hsp2)
 
7921
        return 0;
 
7922
    else if (!hsp1)
 
7923
        return 1;
 
7924
    else if (!hsp2)
 
7925
        return -1;
 
7926
 
 
7927
    if (0 == (result = BLAST_CMP(hsp2->score,          hsp1->score)) &&
 
7928
        0 == (result = BLAST_CMP(hsp1->subject.offset, hsp2->subject.offset)) &&
 
7929
        0 == (result = BLAST_CMP(hsp2->subject.end,    hsp1->subject.end)) &&
 
7930
        0 == (result = BLAST_CMP(hsp1->query  .offset, hsp2->query  .offset))) {
 
7931
        /* if all other test can't distinguish the HSPs, then the final
 
7932
           test is the result */
 
7933
        result = BLAST_CMP(hsp2->query.end, hsp1->query.end);
7851
7934
    }
7852
 
    /* Neither HSP is nil */
7853
 
    else if (h1->score > h2->score)
7854
 
      return -1;
7855
 
    else if (h1->score < h2->score)
7856
 
      return 1;
7857
 
    /* Tie-breakers: decreasing subject offsets; decreasing subject
7858
 
       ends, decreasing query offsets, decreasing query ends */
7859
 
    else if (h1->subject.offset > h2->subject.offset)
7860
 
      return -1;
7861
 
    else if (h1->subject.offset < h2->subject.offset)
7862
 
      return 1;
7863
 
    else if (h1->subject.end > h2->subject.end)
7864
 
      return -1;
7865
 
    else if (h1->subject.end < h2->subject.end)
7866
 
      return 1;
7867
 
    else if (h1->query.offset > h2->query.offset)
7868
 
      return -1;
7869
 
    else if (h1->query.offset < h2->query.offset)
7870
 
      return 1;
7871
 
    else if (h1->query.end > h2->query.end)
7872
 
      return -1;
7873
 
    else if (h1->query.end < h2->query.end)
7874
 
      return 1;
7875
 
 
7876
 
    return 0;
 
7935
    return result;
7877
7936
}
7878
7937
 
7879
7938
/*
7935
7994
}
7936
7995
 
7937
7996
/*
7938
 
        Function to check that the highest scoring region in an HSP still gives a positive
7939
 
        score.  This value was originally calcualted by GetStartForGappedAlignment but it
7940
 
        may have changed due to the introduction of ambiguity characters.  Such a change
7941
 
        can lead to 'strange' results from ALIGN. 
 
7997
   Check whether the starting point for gapped alignment lies in
 
7998
   region that has positive score.  This routine is called after a
 
7999
   preliminary gapped alignment has been computed, but before the
 
8000
   traceback is computed.  The score of the region containing the
 
8001
   starting point may have changed due to the introduction of
 
8002
   ambiguity characters, further filtering of the sequences or the
 
8003
   application of composition based statistics.
 
8004
 
 
8005
   Usually, we check an ungapped alignment of length 11 about the
 
8006
   starting point: 5 characters to the left and 5 to the right.
 
8007
   However, the actual region checked is occassionally shorter because
 
8008
   we don't check characters before the start, or after the end, of
 
8009
   the preliminarily aligned regions in the query or subject.
7942
8010
*/
7943
8011
Boolean
7944
 
CheckStartForGappedAlignment (BlastSearchBlkPtr search, BLAST_HSPPtr hsp, Uint1Ptr query, Uint1Ptr subject, Int4Ptr PNTR matrix)
 
8012
CheckStartForGappedAlignment (BlastSearchBlkPtr search, BLAST_HSPPtr hsp,
 
8013
                              Uint1Ptr query, Uint1Ptr subject,
 
8014
                              Int4Ptr PNTR matrix)
7945
8015
{
7946
 
        Int4 index1, score, start, end, width;
7947
 
        Uint1Ptr query_var, subject_var;
7948
 
        Boolean positionBased = 
7949
 
           (search->positionBased && search->sbp->posMatrix);
7950
 
 
7951
 
        width = MIN((hsp->query.gapped_start-hsp->query.offset), HSP_MAX_WINDOW/2);
7952
 
        start = hsp->query.gapped_start - width;
7953
 
        end = MIN(hsp->query.end, hsp->query.gapped_start + width);
7954
 
        /* Assures that the start of subject is above zero. */
7955
 
        if ((hsp->subject.gapped_start + start - hsp->query.gapped_start) < 0)
7956
 
                start -= hsp->subject.gapped_start + (start - hsp->query.gapped_start);
7957
 
        query_var = query + start;
7958
 
        subject_var = subject + hsp->subject.gapped_start + (start - hsp->query.gapped_start);
7959
 
        score=0;
7960
 
        for (index1=start; index1<end; index1++)
7961
 
        {
7962
 
          if (!positionBased)
7963
 
            score += matrix[*query_var][*subject_var];
7964
 
          else
7965
 
            score += search->sbp->posMatrix[index1][*subject_var];
7966
 
          query_var++; subject_var++;
7967
 
        }
7968
 
        if (score <= 0)
7969
 
                return FALSE;
7970
 
 
7971
 
        return TRUE;
 
8016
    Int4 left, right;       /* Number of aligned characters to the
 
8017
                               left and right of the starting point */
 
8018
    Int4 score;             /* Score of the word alignment */
 
8019
    Uint1Ptr subject_var;   /* Current character in the subject sequence */
 
8020
    Uint1Ptr subject_right; /* last character to be considered in the subject
 
8021
                               sequence */
 
8022
    Boolean positionBased =
 
8023
        (search->positionBased && search->sbp->posMatrix);
 
8024
 
 
8025
    /* Compute the number of characters to the left of the start
 
8026
       to include in the word */
 
8027
    left = -HSP_MAX_WINDOW/2;
 
8028
    if (left < hsp->query.offset - hsp->query.gapped_start) {
 
8029
        left = hsp->query.offset - hsp->query.gapped_start;
 
8030
    }
 
8031
    if (left < hsp->subject.offset - hsp->subject.gapped_start) {
 
8032
        left = hsp->subject.offset - hsp->subject.gapped_start;
 
8033
    }
 
8034
 
 
8035
    /* Compute the number of characters to right to include in the word,
 
8036
       including the starting point itself. */
 
8037
    right = HSP_MAX_WINDOW/2 + 1;
 
8038
    if (right > hsp->query.end - hsp->query.gapped_start) {
 
8039
        right = hsp->query.end - hsp->query.gapped_start;
 
8040
    }
 
8041
    if (right > hsp->subject.end - hsp->subject.gapped_start) {
 
8042
        right = hsp->subject.end - hsp->subject.gapped_start;
 
8043
    }
 
8044
 
 
8045
    /* Calculate the score of the word */
 
8046
    score = 0;
 
8047
    subject_var   = subject + hsp->subject.gapped_start + left;
 
8048
    subject_right = subject + hsp->subject.gapped_start + right;
 
8049
    if ( !positionBased ) {
 
8050
        Uint1Ptr query_var;     /* Current character in the query */
 
8051
        query_var = query + hsp->query.gapped_start + left;
 
8052
        for ( ; subject_var < subject_right; subject_var++, query_var++) {
 
8053
           score += matrix[*query_var][*subject_var];
 
8054
        }
 
8055
    } else {
 
8056
        Int4 query_index;       /* Current position in the query */
 
8057
        query_index = hsp->query.gapped_start + left;
 
8058
        for ( ;  subject_var < subject_right;  subject_var++, query_index++) {
 
8059
            score += search->sbp->posMatrix[query_index][*subject_var];
 
8060
        }
 
8061
    }
 
8062
    if (score <= 0) {
 
8063
        return FALSE;
 
8064
    } else {
 
8065
        return TRUE;
 
8066
    }
7972
8067
}
 
8068
 
 
8069
 
7973
8070
/*
7974
8071
        Gets the ratio used to change an evalue calculated with the subject
7975
8072
        sequence length to one with a db length.
8122
8219
        if (h1->query.offset > h2->query.offset)
8123
8220
                return 1;
8124
8221
 
 
8222
        if (h1->subject.offset < h2->subject.offset)
 
8223
                return -1;
 
8224
        if (h1->subject.offset > h2->subject.offset)
 
8225
                return 1;
 
8226
 
8125
8227
        return 0;
8126
8228
}
8127
8229
 
8148
8250
        if (h1->query.end > h2->query.end)
8149
8251
                return 1;
8150
8252
 
 
8253
        if (h1->subject.end < h2->subject.end)
 
8254
                return -1;
 
8255
        if (h1->subject.end > h2->subject.end)
 
8256
                return 1;
 
8257
 
8151
8258
        return 0;
8152
8259
}
8153
8260
/*
8164
8271
{
8165
8272
        Int4 index1, index, increment;
8166
8273
 
8167
 
        if (search == NULL || *hsp_array == NULL || hsp_count == 0)
 
8274
        if (search == NULL || hsp_array == NULL || hsp_count == 0)
8168
8275
                return 0;
8169
8276
 
8170
8277
        HeapSort(hsp_array, hsp_count, sizeof(BLAST_HSPPtr), query_offset_compare_hsp);
8386
8493
BlastGappedScoreInternal(BlastSearchBlkPtr search, Uint1Ptr subject, Int4 subject_length, GapAlignBlkPtr gap_align, BLAST_HSPPtr *hsp_array, Int4Ptr hspcnt, Int4Ptr hspcnt_max, Int4 hspmax, Int2 frame)
8387
8494
 
8388
8495
{
8389
 
        BLAST_HSPPtr hsp, hsp1;
 
8496
        BLAST_HSPPtr hsp, hsp1=NULL;
8390
8497
        BLAST_HSPPtr PNTR hsp_array_new;
8391
8498
        BLAST_HSP_helperPtr helper;
8392
8499
        Boolean hsp_start_is_contained, hsp_end_is_contained;
8442
8549
                           }
8443
8550
                        }
8444
8551
                }
8445
 
 
 
8552
                
8446
8553
                if (hsp_start_is_contained == FALSE ||
8447
 
                         hsp_end_is_contained == FALSE || 
8448
 
                                hsp->score > hsp1->score)
 
8554
                    hsp_end_is_contained   == FALSE || 
 
8555
                    (hsp1 == NULL) || (hsp->score > hsp1->score))
8449
8556
                {
8450
8557
                        gap_align->include_query = 0;
8451
8558
 
8516
8623
                        hsp->query.length = hsp->query.end - hsp->query.offset;
8517
8624
                        hsp->subject.length = hsp->subject.end - hsp->subject.offset;
8518
8625
                        hsp->score = gap_align->score;
8519
 
/* TLM */
8520
 
                        /* AM: Changed to support query concatenation */
8521
 
                        if( !search->mult_queries )
8522
 
                          hsp->evalue = BlastKarlinStoE_simple(hsp->score, search->sbp->kbp_gap[search->first_context], search->searchsp_eff);
8523
 
                        else
8524
 
                        {
8525
 
                          query_num = GetQueryNum( search->mult_queries,
8526
 
                                                   hsp->query.offset,
8527
 
                                                   hsp->query.end,
8528
 
                                                   hsp->query.frame );
8529
 
                          hsp->evalue = BlastKarlinStoE_simple(hsp->score, 
8530
 
                                                           search->sbp->kbp_gap[search->first_context], 
8531
 
                                                           search->mult_queries->SearchSpEff[query_num]);
8532
 
                        }
 
8626
            if( hsp->score >= search->pbp->cutoff_s1 ) {
 
8627
                /* AM: Changed to support query concatenation */
 
8628
                if( !search->mult_queries )
 
8629
                    hsp->evalue =
 
8630
                        BlastKarlinStoE_simple(hsp->score,
 
8631
                                               search->sbp->
 
8632
                                               kbp_gap[search->first_context],
 
8633
                                               search->searchsp_eff);
 
8634
                else {
 
8635
                    query_num = GetQueryNum( search->mult_queries,
 
8636
                                             hsp->query.offset,
 
8637
                                             hsp->query.end,
 
8638
                                             hsp->query.frame );
 
8639
                    hsp->evalue =
 
8640
                        BlastKarlinStoE_simple(hsp->score,
 
8641
                                               search->sbp->
 
8642
                                               kbp_gap[search->first_context],
 
8643
                                               search->mult_queries->
 
8644
                                               SearchSpEff[query_num]);
 
8645
                }
8533
8646
 
8534
 
                        hsp_cnt++;
8535
 
                        /* Fill in the helper structure. */
8536
 
                        helper[index].qoffset = hsp->query.offset;
8537
 
                        helper[index].qend = hsp->query.end;
8538
 
/*
8539
 
                        helper[index].soffset = hsp->subject.offset;
8540
 
                        helper[index].send = hsp->subject.end;
8541
 
                        helper[index1].qframe = hsp->query.frame;
8542
 
                        helper[index1].sframe = hsp->subject.frame;
8543
 
*/
8544
 
                }
 
8647
                hsp_cnt++;
 
8648
                /* Fill in the helper structure. */
 
8649
                helper[index].qoffset = hsp->query.offset;
 
8650
                helper[index].qend = hsp->query.end;
 
8651
            } else {
 
8652
                /* Score of the gapped extension is below the required
 
8653
                   cutoff, delete this hsp */
 
8654
                hsp_array[index] = BLAST_HSPFree(hsp_array[index]);
 
8655
            }
 
8656
        }
8545
8657
                else
8546
8658
                { /* Contained within another HSP, delete. */
8547
8659
                        hsp_array[index] = BLAST_HSPFree(hsp_array[index]);
8583
8695
BlastNtGappedScoreInternal(BlastSearchBlkPtr search, Uint1Ptr subject, Int4 subject_length, GapAlignBlkPtr gap_align, BLAST_HSPPtr *hsp_array, Int4Ptr hspcnt, Int4Ptr hspcnt_max, Int4 hspmax)
8584
8696
 
8585
8697
{
8586
 
        BLAST_HSPPtr hsp, hsp1;
 
8698
        BLAST_HSPPtr hsp, hsp1=NULL;
8587
8699
        BLAST_HSP_helperPtr helper;
8588
8700
        Boolean hsp_start_is_contained, hsp_end_is_contained;
8589
8701
        Int4 hsp_cnt=0, index, index1, next_offset, query_length;
8801
8913
    return;
8802
8914
}
8803
8915
 
8804
 
static void BLASTCheckHSPInclusion(BLAST_HSPPtr *hsp_array, Int4 hspcnt, 
8805
 
                                   Boolean is_ooframe)
 
8916
void BLASTCheckHSPInclusion(BLAST_HSPPtr *hsp_array, Int4 hspcnt, 
 
8917
                            Boolean is_ooframe)
8806
8918
{
8807
8919
    Int4 index, index1;
8808
8920
    BLAST_HSPPtr hsp, hsp1;
8871
8983
    Int4 index, index1, index2, query_length, max_offset;
8872
8984
    Int4Ptr translated_subject_length=NULL; 
8873
8985
    Int4Ptr translated_subject_length_orig=NULL;
8874
 
    SeqAlignPtr sap, seqalign, seqalign_var, *seqalign_array;
8875
 
    StdSegPtr ssp;
 
8986
    SeqAlignPtr seqalign, seqalign_var, *seqalign_array;
8876
8987
    Uint1Ptr query, PNTR translated_subject=NULL, PNTR translated_subject_orig=NULL;
8877
8988
    ValNodePtr gi_list=NULL;
8878
8989
    BLAST_HitListPtr tmp_hitlist;
9156
9267
                   keep = FALSE;
9157
9268
                }
9158
9269
 
9159
 
                if (keep && search->prog_number == blast_type_blastp ||
9160
 
                    search->prog_number == blast_type_blastn) {
 
9270
                if (keep && (search->prog_number == blast_type_blastp ||
 
9271
                    search->prog_number == blast_type_blastn)) {
9161
9272
                   if (search->pbp->mb_params) {
9162
9273
                      FloatHi searchsp_eff = (FloatHi) search->dblen_eff *
9163
9274
                         (FloatHi) search->context[hsp->context].query->effective_length;
9187
9298
                   /*hsp->pvalue = BlastKarlinEtoP(hsp->evalue);*/
9188
9299
                    if (hsp->evalue > search->pbp->cutoff_e) /* put in for comp. based stats. */
9189
9300
                        keep = FALSE;
9190
 
#if 0 /* Not needed any more: percent identity computed for all programs in 
9191
 
         the same way now, just below */
9192
 
                    if (search->pbp->mb_params &&
9193
 
                        search->pbp->mb_params->use_dyn_prog) {
9194
 
                       search->subject->sequence_start = gap_align->subject - 1;
9195
 
                       if (MegaBlastGetHspPercentIdentity(search, hsp) < 
9196
 
                           search->pbp->mb_params->perc_identity) {
9197
 
                          keep = FALSE;
9198
 
                       }
9199
 
                       search->subject->sequence_start = NULL;
9200
 
                    }
9201
 
#endif
9202
9301
                }
9203
9302
 
9204
9303
                if (keep) {
10329
10428
}
10330
10429
 
10331
10430
 
10332
 
#if 0
10333
 
/* TODO: function is not used in this file */
10334
 
/*
10335
 
        Compares two HSP's looking for overlap in both the
10336
 
        query and the subject sequence.  
10337
 
 
10338
 
        if hsp1 should be deleted, then -1 is returned,
10339
 
        if hsp2 should be deleted, then +1 is returned,
10340
 
        if neither should be deleted, then 0 is returned.
10341
 
*/
10342
 
 
10343
 
static Int2 
10344
 
CheckHspOverlap (BLAST_HSPPtr PNTR hsp_array, BLAST_HSPPtr hsp2, Int4 hspcnt, Boolean PNTR hsp_deleted)
10345
 
 
10346
 
{
10347
 
        BLAST_HSPPtr hsp1;
10348
 
        BLAST_SegPtr query, subject;
10349
 
        Int4 index;
10350
 
 
10351
 
        if (hsp_array == NULL || hsp2 == NULL)
10352
 
                return 0;
10353
 
 
10354
 
 
10355
 
        *hsp_deleted = FALSE;
10356
 
        query = &(hsp2->query);
10357
 
        subject = &(hsp2->subject);
10358
 
 
10359
 
        for (index=0; index<hspcnt; index++)
10360
 
        {
10361
 
                hsp1 = hsp_array[index];
10362
 
                if (hsp1 == NULL)
10363
 
                        continue;
10364
 
 
10365
 
                if (SIGN(hsp1->query.frame) != SIGN(query->frame))
10366
 
                        continue;
10367
 
 
10368
 
                if (SIGN(hsp1->subject.frame) != SIGN(subject->frame))
10369
 
                        continue;
10370
 
 
10371
 
                if (hsp1->query.offset > query->offset && 
10372
 
                        hsp1->query.end > query->end) 
10373
 
                        continue;
10374
 
 
10375
 
                if (hsp1->query.offset < query->offset && 
10376
 
                        hsp1->query.end < query->end) 
10377
 
                        continue;
10378
 
 
10379
 
                if (hsp1->subject.offset > subject->offset && 
10380
 
                        hsp1->subject.end > subject->end) 
10381
 
                        continue;
10382
 
 
10383
 
                if (hsp1->subject.offset < subject->offset && 
10384
 
                        hsp1->subject.end < subject->end) 
10385
 
                        continue;
10386
 
 
10387
 
                if (hsp1->score > hsp2->score)
10388
 
                {
10389
 
                        if (*hsp_deleted == FALSE)
10390
 
                        {
10391
 
                                return 1;
10392
 
                        }
10393
 
                }
10394
 
                else
10395
 
                {
10396
 
                        hsp_array[index] = BLAST_HSPFree(hsp_array[index]);
10397
 
                        *hsp_deleted = TRUE;
10398
 
                }
10399
 
        }
10400
 
 
10401
 
        return 0;
10402
 
}
10403
 
#endif
10404
 
 
10405
10431
static void OOF_TranslateHspToDNAP(BLAST_HSPPtr hspp, Int4 length)
10406
10432
{
10407
10433
    Int4 from, to, frame;
10431
10457
{
10432
10458
        BLAST_HitListPtr current_hitlist;
10433
10459
        BLAST_HSPPtr PNTR hsp_array, new_hsp;
10434
 
        BLAST_Score highscore, lowscore;
10435
 
        Int4 hspcnt, hspmax, index, new_index, high_index, old_index, low_index;
 
10460
        Int4 hspcnt, hspmax, high_index, low_index;
10436
10461
 
10437
10462
        current_hitlist = search->current_hitlist;
10438
10463
        hsp_array = current_hitlist->hsp_array;
10512
10537
        }
10513
10538
 
10514
10539
/* Use a binary search to insert the HSP. */
10515
 
 
10516
 
        if (hspcnt != 0)
10517
 
        {
10518
 
                highscore = hsp_array[0]->score;
10519
 
                lowscore = hsp_array[hspcnt-1]->score;
10520
 
        }
10521
 
        else
10522
 
        {
10523
 
                highscore = 0;
10524
 
                lowscore = 0;
10525
 
        }
10526
 
 
10527
 
        if (score >= highscore)
10528
 
        {
10529
 
                new_index = 0;
10530
 
        }
10531
 
        else if (score <= lowscore)
10532
 
        {
10533
 
                new_index = hspcnt;
10534
 
        }
10535
 
        else
10536
 
        {
10537
 
                low_index = 0;
10538
 
                high_index = hspcnt-1;
10539
 
                new_index = (low_index+high_index)/2;
10540
 
                old_index = new_index;
10541
 
 
10542
 
                for (index=0; index<BLAST_SAVE_ITER_MAX; index++)
10543
 
                {
10544
 
                        if (score > hsp_array[new_index]->score)
10545
 
                        {
10546
 
                                high_index = new_index;
10547
 
                        }
10548
 
                        else
10549
 
                        {
10550
 
                                low_index = new_index;
10551
 
                        }
10552
 
                        new_index = (low_index+high_index)/2;
10553
 
                        if (new_index == old_index)
10554
 
                        { /* Perform this check as new_index get rounded DOWN a
10555
 
bove.*/
10556
 
                                if (score < hsp_array[new_index]->score)
10557
 
                                {
10558
 
                                        new_index++;
10559
 
                                }
10560
 
                                break;
10561
 
                        }
10562
 
                        old_index = new_index;
10563
 
                }
10564
 
        }
 
10540
        low_index  = 0;
 
10541
        high_index = hspcnt;
 
10542
        while(low_index < high_index) {
 
10543
            Int4 next_index = (low_index + high_index)/2;
 
10544
            if( score_compare_hsps(&new_hsp, &hsp_array[next_index]) > 0 ) {
 
10545
                low_index = next_index  + 1;
 
10546
            } else {
 
10547
                high_index = next_index;
 
10548
            }
 
10549
        }
10565
10550
 
10566
10551
        if (hspcnt >= hspmax)
10567
10552
        {
10568
 
                if (new_index >= hspcnt)
10569
 
                { /* this HSP is less significant than others on a full list.*/
10570
 
                        new_hsp = BLAST_HSPFree(new_hsp);
10571
 
                        return;
10572
 
                }
10573
 
                else
10574
 
                { /* Delete the last HPS on the list. */
10575
 
                        hspcnt = --current_hitlist->hspcnt;
10576
 
                        hsp_array[hspcnt] = BLAST_HSPFree(hsp_array[hspcnt]);
10577
 
                }
 
10553
            if (low_index >= hspcnt) {
 
10554
                /* this HSP is less significant than others on a full list.*/
 
10555
                new_hsp = BLAST_HSPFree(new_hsp);
 
10556
                return;
 
10557
            } else {
 
10558
                /* Delete the last HPS on the list. */
 
10559
                hspcnt = --current_hitlist->hspcnt;
 
10560
                hsp_array[hspcnt] = BLAST_HSPFree(hsp_array[hspcnt]);
 
10561
            }
10578
10562
        }
10579
 
        current_hitlist->hspcnt++;
10580
 
        Nlm_MemMove((hsp_array+new_index+1), (hsp_array+new_index), (hspcnt-new_index)*sizeof(hsp_array[0]));
10581
 
        hsp_array[new_index] = new_hsp;
 
10563
        /* Move existing elements out of the way */
 
10564
        Nlm_MemMove(&hsp_array[low_index] + 1, &hsp_array[low_index],
 
10565
                    (hspcnt-low_index)*sizeof(hsp_array[0]));
 
10566
        hspcnt = ++current_hitlist->hspcnt;
 
10567
 
 
10568
        /* Insert the new HSP */
 
10569
        hsp_array[low_index] = new_hsp;
10582
10570
        return;
10583
10571
}
10584
10572
 
10802
10790
        new_hsp->query.frame = ContextToFrame(search, context);
10803
10791
        new_hsp->subject.frame = search->subject->frame;
10804
10792
 
10805
 
/* HACK */
10806
 
new_hsp->query.gapped_start = query_gap_start-1;
10807
 
new_hsp->subject.gapped_start = subject_gap_start-1;
 
10793
    new_hsp->query.gapped_start   = query_gap_start;
 
10794
    new_hsp->subject.gapped_start = subject_gap_start;
10808
10795
 
10809
10796
/* If we are saving ALL HSP's, simply save and sort later. */
10810
10797
        if (current_hitlist->do_not_reallocate == FALSE)
11001
10988
}
11002
10989
 
11003
10990
/* Comparison function for sorting gi list */
11004
 
static Int4 LIBCALLBACK Int4Compare(VoidPtr i, VoidPtr j)
 
10991
static int Int4Compare(const void* i, const void* j)
11005
10992
{
11006
10993
  if (*(Int4Ptr)i > *(Int4Ptr)j)
11007
10994
    return (1);
11010
10997
  return (0);
11011
10998
}
11012
10999
 
11013
 
/* 
11014
 
   Remove hits from a SeqAlignPtr that are not from a gi list 
11015
 
*/
11016
 
 
 
11000
/* Remove hits from a SeqAlignPtr that are not from a gi list. The function
 
11001
 * is optimized with an assumption that the incoming gi list is not sorted.
 
11002
 * Since sorting of the gi list may be expensive, the hit gis are found 
 
11003
 * and sorted. Then for each gi in the (presumably large) incoming gi list,
 
11004
 * a binary search is performed to check if it is present in the list of hit
 
11005
 * gis. This procedure is linear in the gi list size. 
 
11006
 */
11017
11007
SeqAlignPtr 
11018
 
BlastPruneSeqAlignByGiList(SeqAlignPtr seqalign, Int4Ptr gi_list, Int4 gi_list_total)
 
11008
BlastPruneSeqAlignByGiList(SeqAlignPtr seqalign, Int4Ptr gi_list, 
 
11009
                           Int4 gi_list_total, Int4 hitlist_size)
11019
11010
{
11020
11011
   SeqAlignPtr head = NULL, last_sap = NULL, next_sap, sap;
11021
11012
   SeqIdPtr sip;
11022
11013
   BioseqPtr bsp;
11023
 
   Int4 index, gi;
 
11014
   Int4 gi = 0, index;
 
11015
   Int4* hit_gis;
 
11016
   Int4 num_hit_gis, gi_index;
 
11017
   Boolean* good_gis;
 
11018
   Boolean good_gi = FALSE;
11024
11019
 
11025
11020
   if (!gi_list || gi_list_total <= 0)
11026
11021
      return NULL;
11027
11022
 
11028
 
   HeapSort((VoidPtr)gi_list, gi_list_total, sizeof(Int4), Int4Compare);
11029
 
 
 
11023
   /* If the size of the gi list is small, sort it and use a different
 
11024
      routine, which takes a sorted list argument. */
 
11025
      
 
11026
   if (hitlist_size >= gi_list_total) {
 
11027
      qsort((void*)gi_list, gi_list_total, sizeof(Int4), Int4Compare);
 
11028
      return BlastPruneSeqAlignBySortedGiList(seqalign, gi_list, 
 
11029
                                              gi_list_total);
 
11030
   }
 
11031
 
 
11032
   hit_gis = (Int4*) MemNew(hitlist_size*sizeof(Int4));
 
11033
 
 
11034
   gi = 0;
 
11035
   index = 0;
 
11036
   /* Find all subject gis in the Seq-align chain */
11030
11037
   for (sap = seqalign; sap; sap = sap->next) {
11031
11038
      sip = SeqAlignId(sap, 1);
11032
11039
      if (sip->choice != SEQID_GI) {
11037
11044
         }
11038
11045
      }
11039
11046
      if (sip->choice == SEQID_GI) {
11040
 
         gi = sip->data.intvalue;
11041
 
         index = BinarySearchInt4(gi, gi_list, gi_list_total);
11042
 
         if (gi_list[index] == gi) {
11043
 
            next_sap = Malloc(sizeof(SeqAlign));
11044
 
            MemCpy(next_sap, sap, sizeof(SeqAlign));
11045
 
            if (head == NULL)
11046
 
               head = last_sap = next_sap;
11047
 
            else {
11048
 
               last_sap->next = next_sap;
11049
 
               last_sap = last_sap->next;
11050
 
            }
11051
 
         }
11052
 
      }
11053
 
   }
11054
 
   if (last_sap)
11055
 
      last_sap->next = NULL;
 
11047
         /* Save this gi if the previous value of gi 
 
11048
            is different from the current value. */
 
11049
         if (gi != sip->data.intvalue) {
 
11050
           gi = sip->data.intvalue;
 
11051
           hit_gis[index] = gi;
 
11052
           ++index;
 
11053
         }
 
11054
      }
 
11055
   }
 
11056
   num_hit_gis = index;
 
11057
   qsort((void*)hit_gis, num_hit_gis, sizeof(Int4), 
 
11058
         Int4Compare);
 
11059
   good_gis = (Boolean*) MemNew(num_hit_gis*sizeof(Boolean));
 
11060
 
 
11061
   for (index = 0; index < gi_list_total; ++index) {
 
11062
      gi_index = BinarySearchInt4(gi_list[index], hit_gis, num_hit_gis);
 
11063
      if (hit_gis[gi_index] == gi_list[index])
 
11064
         good_gis[gi_index] = TRUE;
 
11065
   }
 
11066
 
 
11067
   for (sap = seqalign; sap; sap = next_sap) {
 
11068
      next_sap = sap->next;
 
11069
      sip = SeqAlignId(sap, 1);
 
11070
      if (sip->choice != SEQID_GI) {
 
11071
         bsp = BioseqLockById(sip);
 
11072
         if (bsp) {
 
11073
            sip = SeqIdFindBest(bsp->id, SEQID_GI);
 
11074
            BioseqUnlock(bsp);
 
11075
         }
 
11076
      }
 
11077
      if (sip->choice == SEQID_GI) {
 
11078
         /* Do the following check only if the previous value of gi 
 
11079
            is different from the current value. */
 
11080
         if (gi != sip->data.intvalue) {
 
11081
            gi = sip->data.intvalue;
 
11082
            index = BinarySearchInt4(gi, hit_gis, num_hit_gis);
 
11083
            good_gi = good_gis[index];
 
11084
         }
 
11085
      } else {
 
11086
         good_gi = FALSE;
 
11087
      }
 
11088
      if (good_gi) {
 
11089
         /* Advance the pointer to the last link in the pruned chain to 
 
11090
            the current Seq-align. */
 
11091
         if (head == NULL)
 
11092
            head = last_sap = sap;
 
11093
         else {
 
11094
            last_sap = sap;
 
11095
         }
 
11096
      } else {
 
11097
         /* Link last Seq-align in the pruned chain to the next Seq-align
 
11098
            in the original chain. */
 
11099
         if (last_sap)
 
11100
            last_sap->next = sap->next;
 
11101
         sap->next = NULL;
 
11102
         /* Free this Seq-align, since it's no longer needed. */
 
11103
         sap = SeqAlignFree(sap);
 
11104
      }
 
11105
   }
 
11106
 
 
11107
 
 
11108
   return head;
 
11109
}
 
11110
 
 
11111
/* Remove hits from a SeqAlignPtr that are not from a sorted gi list.
 
11112
 * No check is made that incoming gi list is sorted. User must make
 
11113
 * sure that it is that way. The pruning is done by a single pass over the
 
11114
 * list of Seq-aligns, in which a binary search is performed for any new 
 
11115
 * subject gi to check if it is present in the gi list.
 
11116
 */
 
11117
SeqAlignPtr 
 
11118
BlastPruneSeqAlignBySortedGiList(SeqAlignPtr seqalign, Int4Ptr gi_list, 
 
11119
                                 Int4 gi_list_total)
 
11120
{
 
11121
   SeqAlignPtr head = NULL, last_sap = NULL, next_sap, sap;
 
11122
   SeqIdPtr sip;
 
11123
   BioseqPtr bsp;
 
11124
   Int4 gi = 0;
 
11125
   Boolean good_gi = FALSE;
 
11126
 
 
11127
   if (!gi_list || gi_list_total <= 0)
 
11128
      return NULL;
 
11129
 
 
11130
   /* Find all subject gis in the Seq-align chain */
 
11131
   for (sap = seqalign; sap; sap = next_sap) {
 
11132
      next_sap = sap->next;
 
11133
      sip = SeqAlignId(sap, 1);
 
11134
      if (sip->choice != SEQID_GI) {
 
11135
         bsp = BioseqLockById(sip);
 
11136
         if (bsp) {
 
11137
            sip = SeqIdFindBest(bsp->id, SEQID_GI);
 
11138
            BioseqUnlock(bsp);
 
11139
         }
 
11140
      }
 
11141
      if (sip->choice == SEQID_GI) {
 
11142
         /* Do the following check only if the previous value of gi is
 
11143
            different from the current value. Otherwise the "good_gi" 
 
11144
            variable is left with its previous value. */
 
11145
         if (gi != sip->data.intvalue) {
 
11146
            Int4 index;
 
11147
            gi = sip->data.intvalue;
 
11148
            index = BinarySearchInt4(gi, gi_list, gi_list_total);
 
11149
            good_gi = (gi_list[index] == gi); 
 
11150
         }
 
11151
      } else {
 
11152
         good_gi = FALSE;
 
11153
      }
 
11154
 
 
11155
      if (good_gi) {
 
11156
         /* Advance the pointer to the last link in the pruned chain to 
 
11157
            the current Seq-align. */
 
11158
         if (head == NULL)
 
11159
            head = last_sap = sap;
 
11160
         else {
 
11161
            last_sap = sap;
 
11162
         }
 
11163
      } else {
 
11164
         /* Link last Seq-align in the pruned chain to the next Seq-align
 
11165
            in the original chain. */
 
11166
         if (last_sap)
 
11167
            last_sap->next = sap->next;
 
11168
         sap->next = NULL;
 
11169
         /* Free this Seq-align, since it's no longer needed. */
 
11170
         sap = SeqAlignFree(sap);
 
11171
      }
 
11172
   }
 
11173
 
11056
11174
   return head;
11057
11175
}
11058
11176
 
11065
11183
BlastPruneSeqAlignByEvalueRange(SeqAlignPtr seqalign, FloatHi expect_low,
11066
11184
                           FloatHi expect_high)
11067
11185
{
11068
 
   SeqAlignPtr head = NULL, last_sap = NULL, next_sap, sap;
 
11186
   SeqAlignPtr head = NULL, last_sap = NULL, sap, next_sap;
11069
11187
   Int4 score, number;
11070
11188
   FloatHi evalue, bit_score;
11071
11189
   SeqIdPtr sip = NULL;
11072
11190
 
11073
 
   for (sap = seqalign; sap; sap = sap->next) {
 
11191
   for (sap = seqalign; sap; sap = next_sap) {
 
11192
      next_sap = sap->next;
11074
11193
      GetScoreAndEvalue(sap, &score, &bit_score, &evalue, &number);
11075
11194
      if (evalue >= expect_low && evalue <= expect_high) {
11076
 
         next_sap = Malloc(sizeof(SeqAlign));
11077
 
         MemCpy(next_sap, sap, sizeof(SeqAlign));
 
11195
         /* Leave this Seq-align */
 
11196
         if (head == NULL)
 
11197
            head = last_sap = sap;
 
11198
         else {
 
11199
            last_sap = sap;
 
11200
         }
11078
11201
 
11079
11202
         if (sip && SeqIdComp(TxGetSubjectIdFromSeqAlign(sap), sip) 
11080
11203
             == SIC_YES) {
11083
11206
         }
11084
11207
         sip = NULL;
11085
11208
 
11086
 
         if (head == NULL)
11087
 
            head = last_sap = next_sap;
11088
 
         else {
11089
 
            last_sap->next = next_sap;
11090
 
            last_sap = last_sap->next;
 
11209
      } else {
 
11210
         if (evalue < expect_low && sip == NULL) {
 
11211
            sip = TxGetSubjectIdFromSeqAlign(sap);
11091
11212
         }
11092
 
      } else if (evalue < expect_low && sip == NULL)
11093
 
         sip = TxGetSubjectIdFromSeqAlign(sap);
 
11213
         /* Remove this Seq-align: link last Seq-align in the pruned
 
11214
            chain to the next Seq-align in the original chain. */
 
11215
         if (last_sap)
 
11216
            last_sap->next = sap->next;
 
11217
         sap->next = NULL;
 
11218
         /* Free this Seq-align, since it's no longer needed. */
 
11219
         sap = SeqAlignFree(sap);
 
11220
      }
11094
11221
 
11095
11222
   }
11096
 
   if (last_sap)
11097
 
      last_sap->next = NULL;
11098
11223
   return head;
11099
11224
}
11100
11225
 
12122
12247
                MakeBlastScore(&score_set, scoretype, 0.0, score);
12123
12248
 
12124
12249
        prob = hsp->e_value;
12125
 
        if (hsp->number == 1)
 
12250
        if (hsp->number <= 1)
12126
12251
        {
12127
12252
                scoretype = "e_value";
12128
12253
        }
12161
12286
        return score_set;
12162
12287
}
12163
12288
 
 
12289
/** Configure the database chunk size adaptively.
 
12290
 * Note: Must be called from a single-threaded context
 
12291
 * @param search the The search block to configure [inout]
 
12292
 * @param num_seq The number of sequences in the database [in]
 
12293
 */
 
12294
void ConfigureDbChunkSize(BlastSearchBlkPtr search, Int4 num_seq)
 
12295
{
 
12296
/* Emit a tick after how many sequences? */
 
12297
search->thr_info->db_incr = num_seq / BLAST_NTICKS;
 
12298
 
 
12299
/* Divide the search into chunks */
 
12300
search->thr_info->db_chunk_size = MAX(num_seq / 100,1);
 
12301
 
 
12302
/* Loadbalance more finely for multithreaded searches. */
 
12303
if (NlmThreadsAvailable() && search->pbp->process_num > 1)
 
12304
    search->thr_info->db_chunk_size = MAX(num_seq/(100*(search->pbp->process_num
 
12305
)), 1);
 
12306
 
 
12307
return;
 
12308
}