~ubuntu-branches/ubuntu/edgy/ncbi-tools6/edgy

« back to all changes in this revision

Viewing changes to algo/blast/core/blast_stat.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2006-07-19 23:28:07 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20060719232807-et3cdmcjgmnyleyx
Tags: 6.1.20060507-3ubuntu1
Re-merge with Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: blast_stat.c,v 1.136 2005/11/14 15:55:42 madden Exp $
 
1
/* $Id: blast_stat.c,v 1.141 2006/04/20 19:28:30 madden Exp $
2
2
 * ===========================================================================
3
3
 *
4
4
 *                            PUBLIC DOMAIN NOTICE
50
50
 
51
51
#ifndef SKIP_DOXYGEN_PROCESSING
52
52
static char const rcsid[] = 
53
 
    "$Id: blast_stat.c,v 1.136 2005/11/14 15:55:42 madden Exp $";
 
53
    "$Id: blast_stat.c,v 1.141 2006/04/20 19:28:30 madden Exp $";
54
54
#endif /* SKIP_DOXYGEN_PROCESSING */
55
55
 
56
56
#include <algo/blast/core/blast_stat.h>
2056
2056
 
2057
2057
 
2058
2058
/**
2059
 
 * Find positive solution to sum_{i=low}^{high} exp(i lambda) = 1.
2060
 
 * 
2061
 
 * @param probs probabilities of a score occurring 
2062
 
 * @param d the gcd of the possible scores. This equals 1 if the scores
2063
 
 * are not a lattice
2064
 
 * @param low the lowest possible score
2065
 
 * @param high the highest possible score
2066
 
 * @param lambda0 an initial value for lambda
2067
 
 * @param tolx the tolerance to which lambda must be computed
2068
 
 * @param itmax the maximum number of times the function may be
2069
 
 * evaluated
2070
 
 * @param maxNewton the maximum permissible number of Newton
2071
 
 * iteration. After that the computation will proceed by bisection.
2072
 
 * @param itn a pointer to an integer that will receive the actually
2073
 
 * number of iterations performed.
2074
 
 *
2075
 
 * Let phi(lambda) =  sum_{i=low}^{high} exp(i lambda) - 1. Then phi(lambda)
2076
 
 * may be written
2077
 
 *
2078
 
 *     phi(lamdba) = exp(u lambda) p( exp(-lambda) )
2079
 
 *
2080
 
 * where p(x) is a polynomial that has exactly two zeros, one at x = 1
2081
 
 * and one at y = exp(-lamdba). It is simpler, more numerically
2082
 
 * efficient and stable to apply Newton's method to p(x) than to
2083
 
 * phi(lambda).
2084
 
 *
2085
 
 * We define a safeguarded Newton iteration as follows. Let the
2086
 
 * initial interval of uncertainty be [0,1]. If p'(x) >= 0, we bisect
2087
 
 * the interval. Otherwise we try a Newton step. If the Newton iterate
2088
 
 * lies in the current interval of uncertainty and it reduces the
2089
 
 * value of | p(x) | by at least 10%, we accept the new
2090
 
 * point. Otherwise, we bisect the current interval of uncertainty.
2091
 
 * It is clear that this method converges to a zero of p(x).  Since
2092
 
 * p'(x) > 0 in an interval containing x = 1, the method cannot
2093
 
 * converge to x = 1 and therefore converges to the only other zero,
2094
 
 * y.
 
2059
 * Find positive solution to 
 
2060
 *
 
2061
 *     sum_{i=low}^{high} exp(i lambda) * probs[i] = 1.
 
2062
 * 
 
2063
 * Note that this solution does not exist unless the average score is
 
2064
 * negative and the largest score that occurs with nonzero probability
 
2065
 * is positive.
 
2066
 * 
 
2067
 * @param probs         probabilities of a score occurring 
 
2068
 * @param d             the gcd of the possible scores. This equals 1 if
 
2069
 *                      the scores are not a lattice
 
2070
 * @param low           the lowest possible score that occurs with
 
2071
 *                      nonzero probability
 
2072
 * @param high          the highest possible score that occurs with
 
2073
 *                      nonzero probability.
 
2074
 * @param lambda0       an initial guess for lambda
 
2075
 * @param tolx          the tolerance to which lambda must be computed
 
2076
 * @param itmax         the maximum number of times the function may be
 
2077
 *                      evaluated
 
2078
 * @param maxNewton     the maximum permissible number of Newton
 
2079
 *                      iterations; after that the computation will proceed
 
2080
 *                      by bisection.
 
2081
 * @param *itn          the number of iterations needed to compute Lambda,
 
2082
 *                      or itmax if Lambda could not be computed.
 
2083
 *
 
2084
 * Let phi(lambda) =  sum_{i=low}^{high} exp(i lambda) - 1. Then
 
2085
 * phi(lambda) may be written
 
2086
 *
 
2087
 *     phi(lamdba) = exp(u lambda) f( exp(-lambda) )
 
2088
 *
 
2089
 * where f(x) is a polynomial that has exactly two zeros, one at x = 1
 
2090
 * and one at x = exp(-lamdba).  It is simpler to solve this problem
 
2091
 * in x = exp(-lambda) than it is to solve it in lambda, because we
 
2092
 * know that for x, a solution lies in [0,1], and because Newton's
 
2093
 * method is generally more stable and efficient for polynomials than
 
2094
 * it is for exponentials.
 
2095
 * 
 
2096
 * For the most part, this function is a standard safeguarded Newton
 
2097
 * iteration: define an interval of uncertainty [a,b] with f(a) > 0
 
2098
 * and f(b) < 0 (except for the initial value b = 1, where f(b) = 0);
 
2099
 * evaluate the function and use the sign of that value to shrink the
 
2100
 * interval of uncertainty; compute a Newton step; and if the Newton
 
2101
 * step suggests a point outside the interval of uncertainty or fails
 
2102
 * to decrease the function sufficiently, then bisect.  There are
 
2103
 * three further details needed to understand the algorithm:
 
2104
 *
 
2105
 * 1)  If y the unique solution in [0,1], then f is positive to the left of
 
2106
 *     y, and negative to the right.  Therefore, we may determine whether
 
2107
 *     the Newton step -f(x)/f'(x) is moving toward, or away from, y by
 
2108
 *     examining the sign of f'(x).  If f'(x) >= 0, we bisect instead
 
2109
 *     of taking the Newton step.
 
2110
 * 2)  There is a neighborhood around x = 1 for which f'(x) >= 0, so
 
2111
 *     (1) prevents convergence to x = 1 (and for a similar reason
 
2112
 *     prevents convergence to x = 0, if the function is incorrectly
 
2113
 *     called with probs[high] == 0).
 
2114
 * 3)  Conditions like  fabs(p) < lambda_tolerance * x * (1-x) are used in
 
2115
 *     convergence criteria because these values translate to a bound
 
2116
 *     on the relative error in lambda.  This is proved in the
 
2117
 *     "Blast Scoring Parameters" document that accompanies the BLAST
 
2118
 *     code.
 
2119
 *
 
2120
 * The iteration on f(x) is robust and doesn't overflow; defining a
 
2121
 * robust safeguarded Newton iteration on phi(lambda) that cannot
 
2122
 * converge to lambda = 0 and that is protected against overflow is
 
2123
 * more difficult.  So (despite the length of this comment) the Newton
 
2124
 * iteration on f(x) is the simpler solution.
2095
2125
 */
2096
 
 
2097
2126
static double 
2098
 
NlmKarlinLambdaNR( double* probs, Int4 d, Int4 low, Int4 high, double lambda0, double tolx,
2099
 
                            Int4 itmax, Int4 maxNewton, Int4 * itn ) 
 
2127
NlmKarlinLambdaNR(double* probs, Int4 d, Int4 low, Int4 high, double lambda0,
 
2128
                  double tolx, Int4 itmax, Int4 maxNewton, Int4 * itn ) 
2100
2129
{
2101
2130
  Int4 k;
2102
2131
  double x0, x, a = 0, b = 1;
2343
2372
Int2
2344
2373
Blast_ScoreBlkKbpUngappedCalc(EBlastProgramType program, 
2345
2374
                              BlastScoreBlk* sbp, Uint1* query, 
2346
 
                              const BlastQueryInfo* query_info)
 
2375
                              const BlastQueryInfo* query_info,
 
2376
                              Blast_Message* *blast_message)
2347
2377
{
 
2378
   Int2 status = 0;
2348
2379
   Int4 context; /* loop variable. */
2349
 
   Boolean query_valid = FALSE;
2350
2380
   Blast_ResFreq* rfp,* stdrfp;
2351
 
   Int2 status = 0;
 
2381
   BlastContextInfo* contexts = query_info->contexts;
2352
2382
   Boolean check_ideal = 
2353
2383
      (program == eBlastTypeBlastx || program == eBlastTypeTblastx ||
2354
2384
       program == eBlastTypeRpsTblastn);
 
2385
   Boolean valid_context = FALSE;
 
2386
 
 
2387
   ASSERT(contexts);
2355
2388
 
2356
2389
   /* Ideal Karlin block is filled unconditionally. */
2357
2390
   status = Blast_ScoreBlkKbpIdealCalc(sbp);
2369
2402
      Int4 query_length;
2370
2403
      Uint1 *buffer;              /* holds sequence */
2371
2404
      Blast_KarlinBlk* kbp;
2372
 
      
2373
 
      /* For each query, check if forward strand is present */
2374
 
      if ((query_length = query_info->contexts[context].query_length) < 0)
2375
 
         continue;
2376
 
      
2377
 
      context_offset = query_info->contexts[context].query_offset;
 
2405
      Int2 loop_status; /* status flag for functions in this loop. */
 
2406
      
 
2407
      if ( !contexts[context].is_valid )
 
2408
          continue;
 
2409
 
 
2410
      query_length = contexts[context].query_length;
 
2411
      context_offset = contexts[context].query_offset;
2378
2412
      buffer = &query[context_offset];
2379
2413
      
2380
2414
      Blast_ResFreqString(sbp, rfp, (char*)buffer, query_length);
2381
2415
      sbp->sfp[context] = Blast_ScoreFreqNew(sbp->loscore, sbp->hiscore);
2382
2416
      BlastScoreFreqCalc(sbp, sbp->sfp[context], rfp, stdrfp);
2383
2417
      sbp->kbp_std[context] = kbp = Blast_KarlinBlkNew();
2384
 
      status = Blast_KarlinBlkUngappedCalc(kbp, sbp->sfp[context]);
2385
 
      if (status) {
2386
 
         continue;
 
2418
      loop_status = Blast_KarlinBlkUngappedCalc(kbp, sbp->sfp[context]);
 
2419
      if (loop_status) {
 
2420
          contexts[context].is_valid = FALSE;
 
2421
          sbp->sfp[context] = Blast_ScoreFreqFree(sbp->sfp[context]);
 
2422
          sbp->kbp_std[context] = Blast_KarlinBlkFree(sbp->kbp_std[context]);
 
2423
          if (!Blast_QueryIsTranslated(program) ) {
 
2424
             Blast_MessageWrite(blast_message, eBlastSevWarning, context,
 
2425
                "Could not calculate ungapped Karlin-Altschul parameters due "
 
2426
                "to an invalid query sequence or its translation. Please verify the "
 
2427
                "query sequence(s) and/or filtering options");
 
2428
          }
 
2429
          continue;
2387
2430
      }
2388
2431
      /* For searches with translated queries, check whether ideal values
2389
2432
         should be substituted instead of calculated values, so a more 
2392
2435
         Blast_KarlinBlkCopy(kbp, sbp->kbp_ideal);
2393
2436
 
2394
2437
      sbp->kbp_psi[context] = Blast_KarlinBlkNew();
2395
 
      if ((status = Blast_KarlinBlkUngappedCalc(sbp->kbp_psi[context], 
2396
 
                                                sbp->sfp[context])) == 0)
2397
 
         query_valid = TRUE;
 
2438
      loop_status = Blast_KarlinBlkUngappedCalc(sbp->kbp_psi[context], 
 
2439
                                           sbp->sfp[context]);
 
2440
      if (loop_status) {
 
2441
          contexts[context].is_valid = FALSE;
 
2442
          sbp->sfp[context] = Blast_ScoreFreqFree(sbp->sfp[context]);
 
2443
          sbp->kbp_std[context] = Blast_KarlinBlkFree(sbp->kbp_std[context]);
 
2444
          sbp->kbp_psi[context] = Blast_KarlinBlkFree(sbp->kbp_psi[context]);
 
2445
          continue;
 
2446
      }
 
2447
      valid_context = TRUE;
2398
2448
   }
2399
2449
 
2400
2450
   rfp = Blast_ResFreqFree(rfp);
2401
2451
   stdrfp = Blast_ResFreqFree(stdrfp);
2402
2452
 
2403
 
   if (query_valid)
2404
 
      status = 0;
2405
 
   else 
2406
 
      return status;
 
2453
   if (valid_context == FALSE)
 
2454
     status = 1;  /* Not a single context was valid. */
2407
2455
 
2408
2456
   /* Set ungapped Blast_KarlinBlk* alias */
2409
2457
   sbp->kbp = (program == eBlastTypePsiBlast) ? sbp->kbp_psi : sbp->kbp_std;
2719
2767
   sfree(beta_arr);
2720
2768
}
2721
2769
 
 
2770
/** Splits an ArrayOf8 into two arrays of supported gap costs.  One is for non-affine 
 
2771
 * (megablast linear values) and the other is for standard (typically affine) values.
 
2772
 * @param input the array to be split [in]
 
2773
 * @param normal the standard (typically affine) values [out]
 
2774
 * @param non_affine the megablast (linear) values [out]
 
2775
 * @param split Boolean specifying whether the non-affine values are populated [out]
 
2776
 * @return 0 on success, -1 on error
 
2777
*/
2722
2778
static Int2
2723
2779
s_SplitArrayOf8(const array_of_8* input, const array_of_8** normal, const array_of_8** non_affine, Boolean *split)
2724
2780
{
2923
2979
            char buffer[256];
2924
2980
            sprintf(buffer, "Substitution scores %d and %d are not supported", 
2925
2981
                reward, penalty);
2926
 
            Blast_MessageWrite(error_return, eBlastSevError, 0, 0, buffer);
 
2982
            Blast_MessageWrite(error_return, eBlastSevError, kBlastMessageNoContext, buffer);
2927
2983
        }
2928
2984
    }
2929
2985
    if (split)
3008
3064
         }
3009
3065
 
3010
3066
         if (!found)
3011
 
         {
3012
 
             *gap_existence = gap_existence_max;
3013
 
             *gap_extension = gap_extension_max;
 
3067
         {   /* If values are above max, then use. Otherwise set max values. */
 
3068
             if (*gap_existence < gap_existence_max || *gap_extension < gap_extension_max)
 
3069
             { 
 
3070
                 *gap_existence = gap_existence_max;
 
3071
                 *gap_extension = gap_extension_max;
 
3072
             }
3014
3073
         }
3015
3074
         status = 0;
3016
3075
   }
3058
3117
            sprintf(buffer, "Gap existence and extension values of %ld and %ld are supported", (long) BLAST_Nint(values[index][0]), (long) BLAST_Nint(values[index][1]));
3059
3118
         else
3060
3119
            sprintf(buffer, "Gap existence, extension and decline-to-align values of %ld, %ld and %ld are supported", (long) BLAST_Nint(values[index][0]), (long) BLAST_Nint(values[index][1]), (long) BLAST_Nint(values[index][2]));
3061
 
         Blast_MessageWrite(error_return, eBlastSevError, 0, 0, buffer);
 
3120
         Blast_MessageWrite(error_return, eBlastSevError, kBlastMessageNoContext, buffer);
3062
3121
      }
3063
3122
   }
3064
3123
 
3092
3151
         vnp = head = BlastLoadMatrixValues();
3093
3152
 
3094
3153
         sprintf(buffer, "%s is not a supported matrix", matrix_name);
3095
 
         Blast_MessageWrite(error_return, eBlastSevError, 0, 0, buffer);
 
3154
         Blast_MessageWrite(error_return, eBlastSevError, kBlastMessageNoContext, buffer);
3096
3155
 
3097
3156
         while (vnp)
3098
3157
         {
3099
3158
            matrix_info = vnp->ptr;
3100
3159
            sprintf(buffer, "%s is a supported matrix", matrix_info->name);
3101
 
            Blast_MessageWrite(error_return, eBlastSevError, 0, 0, buffer);
 
3160
            Blast_MessageWrite(error_return, eBlastSevError, kBlastMessageNoContext, buffer);
3102
3161
            vnp = vnp->next;
3103
3162
         }
3104
3163
 
3110
3169
            sprintf(buffer, "Gap existence and extension values of %ld and %ld not supported for %s", (long) gap_open, (long) gap_extend, matrix_name);
3111
3170
         else
3112
3171
            sprintf(buffer, "Gap existence, extension and decline-to-align values of %ld, %ld and %ld not supported for %s", (long) gap_open, (long) gap_extend, (long) decline_align, matrix_name);
3113
 
         Blast_MessageWrite(error_return, eBlastSevError, 0, 0, buffer);
 
3172
         Blast_MessageWrite(error_return, eBlastSevError, kBlastMessageNoContext, buffer);
3114
3173
         BlastKarlinReportAllowedValues(matrix_name, error_return);
3115
3174
      }
3116
3175
   }
3363
3422
                len = strlen(buffer);
3364
3423
                sprintf(buffer+len, "Any values more stringent than %ld and %ld are supported\n", 
3365
3424
                     (long) gap_open_max, (long) gap_extend_max);
3366
 
                Blast_MessageWrite(error_return, eBlastSevError, 0, 0, buffer);
 
3425
                Blast_MessageWrite(error_return, eBlastSevError, kBlastMessageNoContext, buffer);
3367
3426
                sfree(normal);
3368
3427
                sfree(linear);
3369
3428
                return 1;
4304
4363
 * ===========================================================================
4305
4364
 *
4306
4365
 * $Log: blast_stat.c,v $
 
4366
 * Revision 1.141  2006/04/20 19:28:30  madden
 
4367
 * Prototype change for Blast_MessageWrite
 
4368
 *
 
4369
 * Revision 1.140  2006/04/07 13:45:04  madden
 
4370
 * Improved the comment for NlmKarlinLambdaNR.  Reformatted the
 
4371
 * function prototype to fit in 80 characters. (from Mike Gertz).
 
4372
 *
 
4373
 * Revision 1.139  2006/03/30 14:53:36  madden
 
4374
 * Doxygen comment
 
4375
 *
 
4376
 * Revision 1.138  2006/01/12 20:36:37  camacho
 
4377
 * Changes to Blast_ScoreBlkKbpUngappedCalc to set invalid contexts
 
4378
 *
 
4379
 * Revision 1.137  2005/12/12 13:39:14  madden
 
4380
 * Correction on how gap costs are set if they exceed maximum
 
4381
 *
4307
4382
 * Revision 1.136  2005/11/14 15:55:42  madden
4308
4383
 * Correct comment
4309
4384
 *