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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: phi_lookup.c,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 18:08:29  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.14
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: phi_lookup.c,v 1000.2 2004/06/01 18:08:29 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 phi_lookup.c
  38.  * Functions for accessing the lookup table for PHI-BLAST
  39.  * @todo FIXME needs doxygen comments and lines shorter than 80 characters
  40.  */
  41. static char const rcsid[] = 
  42.     "$Id: phi_lookup.c,v 1000.2 2004/06/01 18:08:29 gouriano Exp $";
  43. #include <algo/blast/core/blast_def.h>
  44. #include <algo/blast/core/blast_util.h>
  45. #include <algo/blast/core/pattern.h>
  46. #include <algo/blast/core/phi_lookup.h>
  47. #include <algo/blast/core/blast_message.h>
  48. #define seedepsilon 0.00001
  49. #define allone  ((1 << ALPHABET_SIZE) - 1)
  50. typedef struct seedSearchItems {
  51.     double  charMultiple[ALPHABET_SIZE];
  52.     double  paramC; /*used in e-value computation*/
  53.     double  paramLambda; /*used in e-value computation*/
  54.     double  paramK; /*used in the bit score computation*/
  55.     Int4         cutoffScore; /*lower bound for what is a hit*/
  56.     double  standardProb[ALPHABET_SIZE]; /*probability of each letter*/
  57.     char         order[ASCII_SIZE];
  58.     char         pchars[ALPHABET_SIZE+1];
  59.     char         name_space[BUF_SIZE];  /*name of a pattern*/
  60.     char         pat_space[PATTERN_SPACE_SIZE];  /*string description
  61.                                                    of pattern*/
  62. } seedSearchItems;
  63. /*Initialize the order of letters in the alphabet, the score matrix,
  64. and the row sums of the score matrix. matrixToFill is the
  65. score matrix, program_flag says which variant of the program is
  66. used; is_dna tells whether the strings are DNA or protein*/
  67. static void init_order(Int4 **matrix, Int4 program_flag, Boolean is_dna, seedSearchItems *seedSearch)
  68. {
  69.     Uint1 i, j; /*loop indices for matrix*/ 
  70.     Int4 *matrixRow; /*row of matrixToFill*/ 
  71.     double rowSum; /*sum of scaled substitution probabilities on matrixRow*/
  72.     
  73.     if (is_dna) {
  74.       seedSearch->order['A'] = 0; 
  75.       seedSearch->order['C'] = 1;
  76.       seedSearch->order['G'] = 2; 
  77.       seedSearch->order['T'] = 3;
  78.     } 
  79.     else {
  80.       for (i = 0; i < ALPHABET_SIZE; i++) 
  81. seedSearch->order[(Uint1)seedSearch->pchars[i]] = i;
  82.     }
  83.     if (program_flag == SEED_FLAG) {
  84.       for (i = 0; i < ALPHABET_SIZE; i++) 
  85.         seedSearch->charMultiple[i] = 0;
  86.       for (i = 0; i < ALPHABET_SIZE; i++) {
  87. if (seedSearch->standardProb[i] > seedepsilon) {
  88.   matrixRow = matrix[i];
  89.   rowSum= 0;
  90.   for (j = 0; j < ALPHABET_SIZE; j++) {
  91.     if (seedSearch->standardProb[j] > seedepsilon) 
  92.       rowSum += seedSearch->standardProb[j]*exp(-(seedSearch->paramLambda)*matrixRow[j]);
  93.   }
  94.   seedSearch->charMultiple[i] = rowSum;
  95. }
  96.       }
  97.     }
  98. }
  99. /*Initialize occurrence probabilities for each amino acid*/
  100. static void initProbs(seedSearchItems * seedSearch)
  101. {
  102.    double totalCount;  /*for Robinson frequencies*/
  103.    seedSearch->pchars[0] = '-';
  104.    seedSearch->pchars[1] = 'A';
  105.    seedSearch->pchars[2] = 'B';
  106.    seedSearch->pchars[3] = 'C';
  107.    seedSearch->pchars[4] = 'D';
  108.    seedSearch->pchars[5] = 'E';
  109.    seedSearch->pchars[6] = 'F';
  110.    seedSearch->pchars[7] = 'G';
  111.    seedSearch->pchars[8] = 'H';
  112.    seedSearch->pchars[9] = 'I';
  113.    seedSearch->pchars[10] = 'K';
  114.    seedSearch->pchars[11] = 'L';
  115.    seedSearch->pchars[12] = 'M';
  116.    seedSearch->pchars[13] = 'N';
  117.    seedSearch->pchars[14] = 'P';
  118.    seedSearch->pchars[15] = 'Q';
  119.    seedSearch->pchars[16] = 'R';
  120.    seedSearch->pchars[17] = 'S';
  121.    seedSearch->pchars[18] = 'T';
  122.    seedSearch->pchars[19] = 'V';
  123.    seedSearch->pchars[20] = 'W';
  124.    seedSearch->pchars[21] = 'X';
  125.    seedSearch->pchars[22] = 'Y';
  126.    seedSearch->pchars[23] = 'Z';
  127.    seedSearch->pchars[24] = 'U';
  128.    seedSearch->pchars[25] = '*';
  129.    totalCount = 78.0 + 19.0 + 54.0 + 63.0 + 39.0 +
  130.     74.0 + 22.0 + 52.0 + 57.0 + 90.0 + 22.0 + 45.0 + 52.0 +
  131.      43.0 + 51.0 + 71.0 + 59.0 + 64.0 + 13.0 + 32.0;
  132.    seedSearch->standardProb[0] = 0.0;
  133.    seedSearch->standardProb[1] = 78.0/totalCount; /*A*/
  134.    seedSearch->standardProb[2] = 0.0;
  135.    seedSearch->standardProb[3] = 19.0/totalCount; /*C*/
  136.    seedSearch->standardProb[4] = 54.0/totalCount; /*D*/
  137.    seedSearch->standardProb[5] = 63.0/totalCount; /*E*/
  138.    seedSearch->standardProb[6] = 39.0/totalCount; /*F*/
  139.    seedSearch->standardProb[7] = 74.0/totalCount; /*G*/
  140.    seedSearch->standardProb[8] = 22.0/totalCount; /*H*/
  141.    seedSearch->standardProb[9] = 52.0/totalCount; /*I*/
  142.    seedSearch->standardProb[10] = 57.0/totalCount; /*K*/
  143.    seedSearch->standardProb[11] = 90.0/totalCount; /*L*/
  144.    seedSearch->standardProb[12] = 22.0/totalCount; /*M*/
  145.    seedSearch->standardProb[13] = 45.0/totalCount; /*N*/
  146.    seedSearch->standardProb[14] = 52.0/totalCount; /*P*/
  147.    seedSearch->standardProb[15] = 43.0/totalCount; /*Q*/
  148.    seedSearch->standardProb[16] = 51.0/totalCount; /*R*/
  149.    seedSearch->standardProb[17] = 71.0/totalCount; /*S*/
  150.    seedSearch->standardProb[18] = 59.0/totalCount; /*T*/
  151.    seedSearch->standardProb[19] = 64.0/totalCount; /*V*/
  152.    seedSearch->standardProb[20] = 13.0/totalCount; /*W*/
  153.    seedSearch->standardProb[21] = 0.0;   /*X*/
  154.    seedSearch->standardProb[22] = 32.0/totalCount;   /*Y*/
  155.    seedSearch->standardProb[23] = 0.0;   /*Z*/
  156.    seedSearch->standardProb[24] = 0.0;   /*U*/
  157. }
  158. /*set uo matches for words that encode 4 DNA characters; figure out
  159.   for each of 256 possible DNA 4-mers, where a prefix matches the pattern
  160.  and where a suffix matches the pattern; store in prefixPos and
  161.  suffixPos; mask has 1 bits for whatever lengths of string
  162. the pattern can match, mask2 has 4 1 bits corresponding to
  163. the last 4 positions of a match; they are used to
  164. do the prefixPos and suffixPos claculations with bit arithmetic*/
  165. static void setting_tt(Int4* S, Int4 mask, Int4 mask2, Uint4* prefixPos, 
  166.        Uint4* suffixPos)
  167. {
  168.   Int4 i; /*index over possible DNA encoded words, 4 bases per word*/
  169.   Int4 tmp; /*holds different mask combinations*/
  170.   Int4 maskLeftPlusOne; /*mask shifted left 1 plus 1; guarantees 1
  171.                            1 character match effectively */
  172.   Uint1 a1, a2, a3, a4;  /*four bases packed into an integer*/
  173.   maskLeftPlusOne = (mask << 1)+1;
  174.   for (i = 0; i < ASCII_SIZE; i++) {
  175.     /*find out the 4 bases packed in integer i*/
  176.     a1 = NCBI2NA_UNPACK_BASE(i, 3);
  177.     a2 = NCBI2NA_UNPACK_BASE(i, 2);
  178.     a3 = NCBI2NA_UNPACK_BASE(i, 1);
  179.     a4 = NCBI2NA_UNPACK_BASE(i, 0);
  180.     /*what positions match a prefix of a4 followed by a3*/
  181.     tmp = ((S[a4]>>1) | mask) & S[a3];
  182.     /*what positions match a prefix of a4 followed by a3 followed by a2*/
  183.     tmp = ((tmp >>1) | mask) & S[a2];
  184.     /*what positions match a prefix of a4, a3, a2,a1*/
  185.     prefixPos[i] = mask2 & ((tmp >>1) | mask) & S[a1];
  186.     
  187.     /*what positions match a suffix of a2, a1*/
  188.     tmp = ((S[a1]<<1) | maskLeftPlusOne) & S[a2];
  189.     /* what positions match a suffix of a3, a2, a1*/
  190.     tmp = ((tmp <<1) | maskLeftPlusOne) & S[a3];
  191.     /*what positions match a suffix of a4, a3, a2, a1*/
  192.     suffixPos[i] = ((((tmp <<1) | maskLeftPlusOne) & S[a4]) << 1) | maskLeftPlusOne;
  193.   }
  194. }
  195. /*initialize mask and other arrays for DNA patterns*/
  196. static void init_pattern_DNA(patternSearchItems *patternSearch)
  197. {
  198.   Int4 mask1; /*mask for one word in a set position*/
  199.   Int4 compositeMask; /*superimposed mask1 in 4 adjacent positions*/
  200.   Int4 wordIndex; /*index over words in pattern*/
  201.   if (patternSearch->flagPatternLength != ONE_WORD_PATTERN) {
  202.     for (wordIndex = 0; wordIndex < patternSearch->numWords; wordIndex++) {
  203.       mask1 = patternSearch->match_maskL[wordIndex];
  204.       compositeMask = mask1 + (mask1>>1)+(mask1>>2)+(mask1>>3);
  205.       setting_tt(patternSearch->SLL[wordIndex], 
  206.       patternSearch->match_maskL[wordIndex], 
  207.  compositeMask, patternSearch->DNAprefixSLL[wordIndex], patternSearch->DNAsuffixSLL[wordIndex]);
  208.     }
  209.   } 
  210.   else {
  211.     compositeMask = patternSearch->match_mask + 
  212.       (patternSearch->match_mask>>1) + 
  213.       (patternSearch->match_mask>>2) + (patternSearch->match_mask>>3); 
  214.     patternSearch->DNAwhichPrefixPosPtr = patternSearch->DNAwhichPrefixPositions; 
  215.     patternSearch->DNAwhichSuffixPosPtr = patternSearch->DNAwhichSuffixPositions;
  216.     setting_tt(patternSearch->whichPositionsByCharacter, 
  217.     patternSearch->match_mask, compositeMask, 
  218.     patternSearch->DNAwhichPrefixPositions, patternSearch->DNAwhichSuffixPositions);
  219.   }
  220. }
  221. /*length is the length of inputPattern, maxLength is a limit on
  222.    how long inputPattern can get;
  223.    return the final length of the pattern or -1 if too long*/
  224. static Int4 expanding(Int4 *inputPatternMasked, Uint1 *inputPattern, 
  225.       Int4 length, Int4 maxLength)
  226. {
  227.     Int4 i, j; /*pattern indices*/
  228.     Int4 numPos; /*number of positions index*/
  229.     Int4  k, t; /*loop indices*/
  230.     Int4 recReturnValue1, recReturnValue2; /*values returned from
  231.                                              recursive calls*/
  232.     Int4 thisPlaceMasked; /*value of one place in inputPatternMasked*/
  233.     Int4 tempPatternMask[MaxP]; /*used as a local representation of
  234.                                part of inputPatternMasked*/
  235.     Uint1 tempPattern[MaxP]; /*used as a local representation of part of
  236.                                inputPattern*/
  237.     for (i = 0; i < length; i++) {
  238.       thisPlaceMasked = -inputPatternMasked[i];
  239.       if (thisPlaceMasked > 0) {  /*represented variable wildcard*/
  240. inputPatternMasked[i] = allone;
  241. for (j = 0; j < length; j++) {
  242.   /*use this to keep track of pattern*/
  243.   tempPatternMask[j] = inputPatternMasked[j]; 
  244.   tempPattern[j] = inputPattern[j];
  245. }
  246. recReturnValue2 = recReturnValue1 = 
  247.   expanding(inputPatternMasked, inputPattern, length, maxLength);
  248. if (recReturnValue1 == -1)
  249.   return -1;
  250. for (numPos = 0; numPos <= thisPlaceMasked; numPos++) {
  251.   if (numPos == 1)
  252.     continue;
  253.   for (k = 0; k < length; k++) {
  254.     if (k == i) {
  255.       for (t = 0; t < numPos; t++) {
  256. inputPatternMasked[recReturnValue1++] = allone;
  257.                 if (recReturnValue1 >= maxLength)
  258.                   return(-1);
  259.       }
  260.     }
  261.     else {
  262.       inputPatternMasked[recReturnValue1] = tempPatternMask[k];
  263.       inputPattern[recReturnValue1++] = tempPattern[k];
  264.               if (recReturnValue1 >= maxLength)
  265.                   return(-1);
  266.     }
  267.     if (recReturnValue1 >= maxLength) 
  268.       return (-1);
  269.   }
  270.   recReturnValue1 = 
  271.     expanding(&inputPatternMasked[recReturnValue2], 
  272.       &inputPattern[recReturnValue2], 
  273.       length + numPos - 1, 
  274.       maxLength - recReturnValue2);
  275.   if (recReturnValue1 == -1) 
  276.     return -1;
  277.   recReturnValue2 += recReturnValue1; 
  278.   recReturnValue1 = recReturnValue2;
  279. }
  280. return recReturnValue1;
  281.       }
  282.     }
  283.     return length;
  284. }
  285. /*Pack the next length bytes of inputPattern into a bit vector
  286.   where the bit is 1 if and only if the byte is non-0 
  287.   Returns packed bit vector*/
  288. static Int4 packing(Uint1 *inputPattern, Int4 length)
  289. {
  290.     Int4 i; /*loop index*/
  291.     Int4 returnValue = 0; /*value to return*/
  292.     for (i = 0; i < length; i++) {
  293.       if (inputPattern[i])
  294. returnValue += (1 << i);
  295.     }
  296.     return returnValue;
  297. }
  298. /*Pack the bit representation of the inputPattern into
  299.    the array patternSearch->match_maskL
  300.    numPlaces is the number of positions in
  301.    inputPattern
  302.    Also packs patternSearch->bitPatternByLetter  */
  303. static void longpacking(Int4 numPlaces, Uint1 *inputPattern, patternSearchItems *patternSearch)
  304. {
  305.     Int4 charIndex; /*index over characters in alphabet*/
  306.     Int4 bitPattern; /*bit pattern for one word to pack*/
  307.     Int4 i;  /*loop index over places*/
  308.     Int4 wordIndex; /*loop counter over words to pack into*/
  309.     
  310.     patternSearch->numWords = (numPlaces-1) / BITS_PACKED_PER_WORD +1;
  311.     for (wordIndex = 0; wordIndex < patternSearch->numWords; wordIndex++) {
  312.       bitPattern = 0;
  313.       for (i = 0; i < BITS_PACKED_PER_WORD; i++) {
  314. if (inputPattern[wordIndex*BITS_PACKED_PER_WORD+i]) 
  315.   bitPattern += (1 << i);
  316.       }
  317.       patternSearch->match_maskL[wordIndex] = bitPattern;
  318.     }
  319.     for (charIndex = 0; charIndex < ALPHABET_SIZE; charIndex++) {
  320.       for (wordIndex = 0; wordIndex < patternSearch->numWords; wordIndex++) {
  321. bitPattern = 0;
  322. for (i = 0; i < BITS_PACKED_PER_WORD; i++) {
  323.   if ((1<< charIndex) & patternSearch->inputPatternMasked[wordIndex*BITS_PACKED_PER_WORD + i]) 
  324.     bitPattern = bitPattern | (1 << i);
  325. }
  326. patternSearch->bitPatternByLetter[charIndex][wordIndex] = 
  327.   bitPattern;
  328. }
  329.     }
  330. }
  331. /*Return the number of 1 bits in the base 2 representation of a*/
  332. static Int4 num_of_one(Int4 a)
  333. {
  334.   Int4 returnValue;
  335.   returnValue = 0;
  336.   while (a > 0) {
  337.     if (a % 2 == 1) 
  338.       returnValue++;
  339.     a = (a >> 1);
  340.   }
  341.   return returnValue;
  342. }
  343. /*Sets up field in patternSearch when pattern is very long*/
  344. static void longpacking2(Int4 *inputPatternMasked, Int4 numPlacesInPattern, patternSearchItems *patternSearch)
  345. {
  346.     Int4 placeIndex; /*index over places in pattern rep.*/
  347.     Int4 wordIndex; /*index over words*/
  348.     Int4 placeInWord, placeInWord2;  /*index for places in a single word*/
  349.     Int4 charIndex; /*index over characters in alphabet*/
  350.     Int4 oneWordMask; /*mask of matching characters for one word in
  351.                         pattern representation*/
  352.     double patternWordProbability;
  353.     double  most_specific; /*lowest probability of a word in the pattern*/
  354.     Int4 *oneWordSLL; /*holds patternSearch->SLL for one word*/
  355.     most_specific = 1.0; 
  356.     patternSearch->whichMostSpecific = 0; 
  357.     patternWordProbability = 1.0;
  358.     for (placeIndex = 0, wordIndex = 0, placeInWord=0; 
  359.  placeIndex <= numPlacesInPattern;   placeIndex++, placeInWord++) {
  360.       if (placeIndex==numPlacesInPattern || inputPatternMasked[placeIndex] < 0 
  361.   || placeInWord == BITS_PACKED_PER_WORD ) {
  362. patternSearch->match_maskL[wordIndex] = 1 << (placeInWord-1);
  363. oneWordSLL = patternSearch->SLL[wordIndex];
  364. for (charIndex = 0; charIndex < ALPHABET_SIZE; charIndex++) {
  365.   oneWordMask = 0;
  366.   for (placeInWord2 = 0; placeInWord2 < placeInWord; placeInWord2++) {
  367.     if ((1<< charIndex) & 
  368. inputPatternMasked[placeIndex-placeInWord+placeInWord2]) 
  369.       oneWordMask |= (1 << placeInWord2);
  370.   }
  371.   oneWordSLL[charIndex] = oneWordMask;
  372. }
  373. patternSearch->numPlacesInWord[wordIndex] = placeInWord;
  374. if (patternWordProbability < most_specific) {
  375.   most_specific = patternWordProbability;
  376.   patternSearch->whichMostSpecific = wordIndex;
  377. }
  378. if (placeIndex == numPlacesInPattern) 
  379.   patternSearch->spacing[wordIndex++] = 0; 
  380. else 
  381.   if (inputPatternMasked[placeIndex] < 0) { 
  382.     patternSearch->spacing[wordIndex++] = -inputPatternMasked[placeIndex];
  383.   }
  384.   else { 
  385.     placeIndex--; 
  386.     patternSearch->spacing[wordIndex++] = 0;
  387.   }
  388. placeInWord = -1; 
  389. patternWordProbability = 1.0;
  390.       }
  391.       else {
  392. patternWordProbability *= (double) 
  393.   num_of_one(inputPatternMasked[placeIndex])/ (double) ALPHABET_SIZE;
  394. }
  395.     }
  396.     patternSearch->numWords = wordIndex;
  397. }
  398. /*pattern is a string describing the pattern to search for;
  399.   is_dna is a boolean describing the strings are DNA or protein*/
  400. static Int4 
  401. init_pattern(Uint1 *pattern, Boolean is_dna, BlastScoreBlk* sbp, 
  402.              patternSearchItems* *pattern_info,
  403.              Blast_Message* *error_msg)
  404. {
  405.     Uint4 i; /*index over string describing the pattern*/
  406.     Uint4 j; /*index for position in pattern*/
  407.     Int4 charIndex; /*index over characters in alphabet*/
  408.     Int4 secondIndex; /*second index into pattern*/
  409.     Int4 numIdentical; /*number of consec. positions with identical specification*/
  410.     Uint4 charSetMask;  /*index over masks for specific characters*/
  411.     Int4 currentSetMask, prevSetMask ; /*mask for current and previous character positions*/    
  412.     Int4 thisMask;    /*integer representing a bit pattern for a 
  413.                         set of characters*/
  414.     Int4 minWildcard, maxWildcard; /*used for variable number of wildcard
  415.                                      positions*/
  416.     Uint4  tj=0; /*temporary copy of j*/
  417.     Int4 tempInputPatternMasked[MaxP]; /*local copy of parts
  418.             of inputPatternMasked*/
  419.     Uint1 c;  /*character occurring in pattern*/
  420.     Uint1 localPattern[MaxP]; /*local variable to hold
  421.                                for each position whether it is
  422.                                last in pattern (1) or not (0) */
  423.     double positionProbability; /*probability of a set of characters
  424.                                     allowed in one position*/
  425.     Int4 currentWildcardProduct; /*product of wildcard lengths for
  426.                                    consecutive character positions that
  427.                                    overlap*/
  428.     seedSearchItems *seedSearch;
  429.     patternSearchItems* patternSearch;
  430.     seedSearch = (seedSearchItems*) calloc(1, sizeof(seedSearchItems));
  431.     patternSearch = *pattern_info = 
  432.        (patternSearchItems*) calloc(1, sizeof(patternSearchItems));
  433.     initProbs(seedSearch);
  434.     init_order(sbp->matrix, PAT_SEED_FLAG, FALSE, seedSearch);
  435.     patternSearch->flagPatternLength = ONE_WORD_PATTERN; 
  436.     patternSearch->patternProbability = 1.0;
  437.     patternSearch->minPatternMatchLength = 0;
  438.     patternSearch->wildcardProduct = 1;
  439.     currentWildcardProduct = 1;
  440.     prevSetMask = 0;
  441.     currentSetMask = 0;
  442.     for (i = 0 ; i < MaxP; i++) {
  443.       patternSearch->inputPatternMasked[i] = 0; 
  444.       localPattern[i] = 0;
  445.     }
  446.     for (i = 0, j = 0; i < strlen((Char *) pattern); i++) {
  447.       if ((c=pattern[i]) == '-' || c == 'n' || c == '.' || c =='>' || c ==' ' 
  448. || c == '<')  /*spacers that mean nothing*/
  449. continue;
  450.       if ( c != '[' && c != '{') { /*not the start of a set of characters*/
  451. if (c == 'x' || c== 'X') {  /*wild-card character matches anything*/
  452.           /*next line checks to see if wild card is for multiple positions*/
  453.   if (pattern[i+1] == '(') {
  454.     i++;
  455.     secondIndex = i;
  456.             /*find end of description of how many positions are wildcarded
  457.                will look like x(2) or x(2,5) */
  458.     while (pattern[secondIndex] != ',' && pattern[secondIndex] != ')')
  459.       secondIndex++;
  460.     if (pattern[secondIndex] == ')') {  /*fixed number of positions wildcarded*/
  461.       i -= 1; 
  462.               /*wildcard, so all characters are allowed*/
  463.       charSetMask=allone; 
  464.       positionProbability = 1;
  465.     }
  466.     else { /*variable number of positions wildcarded*/   
  467.       sscanf((Char*) &pattern[++i], "%d,%d", &minWildcard, &maxWildcard);
  468.       maxWildcard = maxWildcard - minWildcard;
  469.          currentWildcardProduct *= (maxWildcard + 1);
  470.          if (currentWildcardProduct > patternSearch->wildcardProduct)
  471.             patternSearch->wildcardProduct = currentWildcardProduct;
  472.          patternSearch->minPatternMatchLength += minWildcard;
  473.       while (minWildcard-- > 0) { 
  474.             /*use one position each for the minimum number of
  475.               wildcard spaces required */
  476.             patternSearch->inputPatternMasked[j++] = allone; 
  477.             if (j >= MaxP) {
  478.                Blast_MessageWrite(error_msg, BLAST_SEV_WARNING, 2, 1, 
  479.                                   "pattern too long");
  480.                return(-1);
  481.             }
  482.       }
  483.       if (maxWildcard != 0) {
  484.             /*negative masking used to indicate variability
  485.               in number of wildcard spaces; e.g., if pattern looks
  486.               like x(3,5) then variability is 2 and there will
  487.               be three wildcard positions with mask allone followed
  488.               by a single position with mask -2*/
  489.             patternSearch->inputPatternMasked[j++] = -maxWildcard;
  490.             patternSearch->patternProbability *= maxWildcard;
  491.       }
  492.          /*now skip over wildcard description with the i index*/
  493.       while (pattern[++i] != ')') ; 
  494.       continue;
  495.     }
  496.   }
  497.   else {  /*wild card is for one position only*/
  498.     charSetMask=allone; 
  499.     positionProbability =1;
  500.   }
  501. else {
  502.   if (c == 'U') {   /*look for special U character*/
  503.     charSetMask = allone*2+1;
  504.     positionProbability = 1; 
  505.   }
  506.   else { 
  507.         /*exactly one character matches*/
  508.         prevSetMask = currentSetMask;
  509.         currentSetMask =  charSetMask = (1 << seedSearch->order[c]);
  510.         if (!(prevSetMask & currentSetMask)) /*character sets don't overlap*/
  511.            currentWildcardProduct = 1;
  512.         positionProbability = 
  513.            seedSearch->standardProb[(Uint1)seedSearch->order[c]];
  514.   }
  515. }
  516.       }
  517.       else {
  518. if (c == '[') {  /*start of a set of characters allowed*/
  519.   charSetMask = 0;
  520.   positionProbability = 0;
  521.   /*For each character in the set add it to the mask and
  522.             add its probability to positionProbability*/
  523.   while ((c=pattern[++i]) != ']') { /*end of set*/
  524.         if ((c < 'A') || (c > 'Z') || (c == '')) {
  525.            Blast_MessageWrite(error_msg, BLAST_SEV_WARNING, 2, 1, 
  526.                               "pattern description has a non-alphabetic"
  527.                               "character inside a bracket");
  528.            
  529.            return(-1);
  530.         }
  531.         charSetMask = charSetMask | (1 << seedSearch->order[c]);
  532.         positionProbability += seedSearch->standardProb[(Uint1)seedSearch->order[c]];
  533.   }
  534.      prevSetMask = currentSetMask;
  535.      currentSetMask = charSetMask;
  536.   if (!(prevSetMask & currentSetMask)) /*character sets don't overlap*/
  537.       currentWildcardProduct = 1;
  538.   } 
  539. else {   /*start of a set of characters forbidden*/
  540.   /*For each character forbidden remove it to the mask and
  541.             subtract its probability from positionProbability*/
  542.   charSetMask = allone; 
  543.   positionProbability = 1;
  544.   while ((c=pattern[++i]) != '}') { /*end of set*/
  545.     charSetMask = charSetMask -  (charSetMask & (1 << seedSearch->order[c]));
  546.     positionProbability -= seedSearch->standardProb[(Uint1)seedSearch->order[c]];
  547.   }
  548.           prevSetMask = currentSetMask;
  549.           currentSetMask = charSetMask;
  550.   if (!(prevSetMask & currentSetMask)) /*character sets don't overlap*/
  551.       currentWildcardProduct = 1;
  552. }
  553.       }
  554.       /*handle a number of positions that are the same */
  555.       if (pattern[i+1] == '(') {  /*read opening paren*/
  556. i++;
  557. numIdentical = atoi((Char *) &pattern[++i]);  /*get number of positions*/
  558.         patternSearch->minPatternMatchLength += numIdentical;
  559. while (pattern[++i] != ')') ;  /*skip over piece in pattern*/
  560. while ((numIdentical--) > 0) {
  561.   /*set up mask for these positions*/
  562.   patternSearch->inputPatternMasked[j++] = charSetMask;
  563.   patternSearch->patternProbability *= positionProbability; 
  564. }
  565.       } 
  566.       else {   /*specification is for one posiion only*/
  567.          patternSearch->inputPatternMasked[j++] = charSetMask;
  568.          patternSearch->minPatternMatchLength++;
  569.          patternSearch->patternProbability *= positionProbability;
  570.       }
  571.       if (j >= MaxP) {
  572.          Blast_MessageWrite(error_msg, BLAST_SEV_WARNING, 2, 1, 
  573.                             "pattern too long");
  574.       }
  575.     }
  576.     localPattern[j-1] = 1;
  577.     if (patternSearch->patternProbability > 1.0)
  578.       patternSearch->patternProbability = 1.0;
  579.     for (i = 0; i < j; i++) {
  580.       tempInputPatternMasked[i] = patternSearch->inputPatternMasked[i]; 
  581.       tj = j;
  582.     }
  583.     j = expanding(patternSearch->inputPatternMasked, localPattern, j, MaxP);
  584.     if ((j== -1) || ((j > BITS_PACKED_PER_WORD) && is_dna)) {
  585.       patternSearch->flagPatternLength = PATTERN_TOO_LONG;
  586.       longpacking2(tempInputPatternMasked, tj, patternSearch);
  587.       for (i = 0; i < tj; i++) 
  588.          patternSearch->inputPatternMasked[i] = tempInputPatternMasked[i];
  589.       patternSearch->highestPlace = tj;
  590.       if (is_dna) 
  591.          init_pattern_DNA(patternSearch);
  592.       return 1;
  593.     }
  594.     if (j > BITS_PACKED_PER_WORD) {
  595.       patternSearch->flagPatternLength = MULTI_WORD_PATTERN;
  596.       longpacking(j, localPattern, patternSearch);
  597.       return j;
  598.     } 
  599.     /*make a bit mask out of local pattern of length j*/
  600.     patternSearch->match_mask = packing(localPattern, j);
  601.     /*store for each character a bit mask of which positions
  602.       that character can occur in*/
  603.     for (charIndex = 0; charIndex < ALPHABET_SIZE; charIndex++) {
  604.       thisMask = 0;
  605.       for (charSetMask = 0; charSetMask < j; charSetMask++) {
  606. if ((1<< charIndex) & patternSearch->inputPatternMasked[charSetMask]) 
  607.   thisMask |= (1 << charSetMask);
  608.       }
  609.       patternSearch->whichPositionsByCharacter[charIndex] = thisMask;
  610.     }
  611.     patternSearch->whichPositionPtr = patternSearch->whichPositionsByCharacter;
  612.     if (is_dna) 
  613.       init_pattern_DNA(patternSearch);
  614.     return j; /*return number of places for pattern representation*/
  615. }
  616. Int2 PHILookupTableNew(const LookupTableOptions* opt, PHILookupTable* * lut,
  617.                        Boolean is_dna, BlastScoreBlk* sbp)
  618. {
  619.    PHILookupTable* lookup = *lut = 
  620.       (PHILookupTable*) malloc(sizeof(PHILookupTable));
  621.    Blast_Message* error_msg = NULL;
  622.    if (!lookup)
  623.       return -1;
  624.    lookup->is_dna = is_dna;
  625.    init_pattern((Uint1*)opt->phi_pattern, is_dna, sbp, &lookup->pattern_info,
  626.                 &error_msg); 
  627.    lookup->num_matches = 0;
  628.    lookup->allocated_size = MIN_PHI_LOOKUP_SIZE;
  629.    if ((lookup->start_offsets = 
  630.        (Int4*) malloc(MIN_PHI_LOOKUP_SIZE*sizeof(Int4))) == NULL)
  631.       return -1;
  632.    if ((lookup->lengths = (Int4*) malloc(MIN_PHI_LOOKUP_SIZE*sizeof(Int4)))
  633.         == NULL)
  634.       return -1;
  635.    return 0;
  636. }
  637. PHILookupTable* PHILookupTableDestruct(PHILookupTable* lut)
  638. {
  639.    sfree(lut->pattern_info);
  640.    sfree(lut->start_offsets);
  641.    sfree(lut->lengths);
  642.    sfree(lut);
  643.    return NULL;
  644. }
  645. static Int2 PHIBlastAddPatternHit(PHILookupTable* lookup, Int4 offset, 
  646.                                   Int4 length)
  647. {
  648.    if (lookup->num_matches >= lookup->allocated_size) {
  649.       lookup->start_offsets = (Int4*) realloc(lookup->start_offsets, 
  650.                                               2*lookup->allocated_size);
  651.       lookup->lengths = (Int4*) realloc(lookup->lengths, 
  652.                                               2*lookup->allocated_size);
  653.       if (!lookup->start_offsets || !lookup->lengths)
  654.          return -1;
  655.       lookup->allocated_size *= 2;
  656.    }      
  657.       
  658.    lookup->start_offsets[lookup->num_matches] = offset;
  659.    lookup->lengths[lookup->num_matches] = length;
  660.    ++lookup->num_matches;
  661.    return 0;
  662. }
  663. Int4 PHIBlastIndexQuery(PHILookupTable* lookup, 
  664.         BLAST_SequenceBlk* query, ListNode* location, Boolean is_dna)
  665. {
  666.    ListNode* loc;
  667.    Int4 from, to;
  668.    Int4 loc_length;
  669.    Uint1* sequence;
  670.    patternSearchItems* pattern_info = lookup->pattern_info;
  671.    Int4* hitArray;
  672.    Int4 i, twiceNumHits;
  673.    
  674.    hitArray = (Int4 *) calloc(2*query->length, sizeof(Int4));
  675.    for(loc=location; loc; loc=loc->next) {
  676.       from = ((SSeqRange*) loc->ptr)->left;
  677.       to = ((SSeqRange*) loc->ptr)->right;
  678.       loc_length = to - from + 1;
  679.       sequence = query->sequence + from;
  680.       
  681.       twiceNumHits = FindPatternHits(hitArray, sequence, loc_length, is_dna,
  682.                                      pattern_info);
  683.       
  684.       for (i = 0; i < twiceNumHits; i += 2) {
  685.          PHIBlastAddPatternHit(lookup, hitArray[i+1]+from, 
  686.                                hitArray[i]-hitArray[i+1]+1);
  687.       }
  688.    }
  689.    return lookup->num_matches;
  690. }
  691. static Boolean 
  692. PHIBlastMatchPatterns(Uint1* subject, Uint1* query, Int4 length)
  693. {
  694.    Int4 index;
  695.    for (index = 0; index < length; ++index) {
  696.       if (subject[index] != query[index])
  697.          break;
  698.    }
  699.    return (index == length);
  700. }
  701. Int4 PHIBlastScanSubject(const LookupTableWrap* lookup_wrap,
  702.         const BLAST_SequenceBlk *query_blk, 
  703.         const BLAST_SequenceBlk *subject_blk, 
  704.         Int4* offset_ptr, Uint4 * query_offsets, Uint4 * subject_offsets, 
  705.         Int4 array_size)
  706. {
  707.    Uint1* subject, *query;
  708.    PHILookupTable* lookup = (PHILookupTable*) lookup_wrap->lut;
  709.    Int4 index, count = 0, twiceNumHits, i;
  710.    Int4 *start_offsets = lookup->start_offsets;
  711.    Int4 *pat_lengths = lookup->lengths;
  712.    Int4 offset, length;
  713.    Int4 hitArray[MAX_HIT];
  714.    query = query_blk->sequence;
  715.    subject = subject_blk->sequence;
  716.    /* It must be guaranteed that all pattern matches for a given 
  717.       subject sequence are processed in one call to this function.
  718.    */
  719.    *offset_ptr = subject_blk->length;
  720.    twiceNumHits = FindPatternHits(hitArray, subject, subject_blk->length, 
  721.                                   lookup->is_dna, lookup->pattern_info);
  722.    for (i = 0; i < twiceNumHits; i += 2) {
  723. #if 0
  724.       if (count > array_size - lookup->num_matches)
  725.             break;
  726. #endif
  727.       length = hitArray[i] - hitArray[i+1] + 1;
  728.       offset = hitArray[i+1];
  729.       for (index = 0; index < lookup->num_matches; ++index) {
  730.          /* Match pattern lengths in subject in query first; then 
  731.             check for identical match of pattern */
  732.          if (length == pat_lengths[index] &&
  733.              PHIBlastMatchPatterns(subject+offset, query+start_offsets[index], 
  734.                                    length))
  735.          {
  736.             /* Pattern has matched completely. Save index into the array
  737.                of pattern start offsets in query (so pattern length will
  738.                be accessible in the word finder later), and the subject
  739.                offset. */
  740.             query_offsets[count] = index;
  741.             subject_offsets[count] = offset;
  742.             ++count;
  743.          }
  744.       }
  745.    }
  746.    return count;
  747. }