NCBI C Toolkit Cross Reference

C/tools/posit.c


  1 static char const rcsid[] = "$Id: posit.c,v 6.87 2008/10/03 18:09:17 madden Exp $";
  2 
  3 /* $Id: posit.c,v 6.87 2008/10/03 18:09:17 madden Exp $
  4 * ===========================================================================
  5 *
  6 *                            PUBLIC DOMAIN NOTICE
  7 *               National Center for Biotechnology Information
  8 *
  9 *  This software/database is a "United States Government Work" under the
 10 *  terms of the United States Copyright Act.  It was written as part of
 11 *  the author's official duties as a United States Government employee and
 12 *  thus cannot be copyrighted.  This software/database is freely available
 13 *  to the public for use. The National Library of Medicine and the U.S.
 14 *  Government have not placed any restriction on its use or reproduction.
 15 *
 16 *  Although all reasonable efforts have been taken to ensure the accuracy
 17 *  and reliability of the software and data, the NLM and the U.S.
 18 *  Government do not and cannot warrant the performance or results that
 19 *  may be obtained by using this software or data. The NLM and the U.S.
 20 *  Government disclaim all warranties, express or implied, including
 21 *  warranties of performance, merchantability or fitness for any particular
 22 *  purpose.
 23 *
 24 *  Please cite the author in any work or product based on this material.
 25 *
 26 * ===========================================================================
 27 *
 28 
 29    File name: posit.c
 30 
 31   Author: Alejandro Schaffer
 32 
 33   Contents: utilities for position-based BLAST.
 34 
 35   $Revision: 6.87 $ 
 36  *****************************************************************************
 37 
 38  * $Log: posit.c,v $
 39  * Revision 6.87  2008/10/03 18:09:17  madden
 40  * Change a few constants for pseudo counts (from A. Schaffer)
 41  *
 42  * Revision 6.86  2008/07/22 19:45:32  kans
 43  * removed unused variables
 44  *
 45  * Revision 6.85  2008/03/31 16:21:58  kans
 46  * CodeWarrior requred a cast to Blast_GetMatrixBackgroundFreq result
 47  *
 48  * Revision 6.84  2008/03/31 13:36:10  madden
 49  * Implemented a new method to compute effective observations.
 50  * Implemented a new entropy-based method to compute column-specific pseudocounts.
 51  *
 52  * Revision 6.83  2007/05/07 13:30:54  kans
 53  * added casts for Seq-data.gap (SeqDataPtr, SeqGapPtr, ByteStorePtr)
 54  *
 55  * Revision 6.82  2007/03/12 16:21:35  papadopo
 56  * From Kristoffer Osowski: fix a buffer overflow caused by incorrect computation of number of sequences for psiblast
 57  *
 58  * Revision 6.81  2007/01/22 19:20:55  camacho
 59  * From Alejandro Schaffer:
 60  * In posPurgeMatches, when in command-line mode, added a warning for the
 61  * situation in which only the query is used to construct the PSSM.
 62  *
 63  * Revision 6.80  2006/09/28 12:45:39  madden
 64  *        Use more accurrate, symmetric, frequency data for the PAM matrices.
 65  *        Make the frequency ratios for the X character in BLOSUM90 the
 66  *        same consistent with the other BLOSUM matrices.
 67  *        [from Mike Gertz]
 68  *
 69  * Revision 6.79  2006/09/25 19:27:39  madden
 70  *    - Include blastkar.h in posit.c to get the declarations of
 71  *      BlastScoreFreqNew and BlastScoreFreqDestruct
 72  *    - Change %lf in printf statements to %f: %lf is equivalent to %f,
 73  *      but is not ANSI C, so was causing warnings.
 74  *    - Copied the correct, 28-character frequency ratios from
 75  *      algo/blast/core/matrix_freq_ratios.c.
 76  *    [from Mike Gertz]
 77  *
 78  * Revision 6.78  2006/08/01 16:52:07  camacho
 79  * Fix comments
 80  *
 81  * Revision 6.77  2006/06/30 18:44:40  camacho
 82  * Add support for O and J to getRes, ResToInt
 83  *
 84  * Revision 6.76  2005/08/30 18:21:02  coulouri
 85  * From Mike Gertz:
 86  *    In posFreqsToMatrix while setting posSearch->posPrivateMatrix, check
 87  *    whether the frequency ratio is zero before taking the log.  If it is
 88  *    zero, set the score to BLAST_SCORE_MIN.  Do not test whether the
 89  *    original matrix has a score of BLAST_SCORE_MIN.
 90  *
 91  * Revision 6.75  2005/08/05 12:05:13  coulouri
 92  * From Mike Gertz:
 93  * - Changed the freq ratio of a (*,-) or (-,*) match for all matrices to
 94  *   be zero.  The effect of this change is that these substitutions get
 95  *   assigned a score of BLAST_SCORE_MIN when composition-based statistics
 96  *   is used in any mode.
 97  *
 98  * Revision 6.74  2005/07/28 14:57:10  coulouri
 99  * remove dead code
100  *
101  * Revision 6.73  2005/06/08 12:26:29  camacho
102  * Change posReadPosFreqsScoremat to accept other encodings of Bioseq data in ASN.1 PSSM
103  *
104  * Revision 6.72  2004/10/12 15:06:57  papadopo
105  * 1. Modify residue frequency IO to comply with new scoremat spec
106  * 2. Remove check that residue frequencies read from scoremat are <= 1.0
107  * 3. Pass gap open and gap extend penalties into BposComputation and
108  *      CposComputation, so that scoremats can contain them
109  *
110  * Revision 6.71  2004/08/23 17:09:22  papadopo
111  * From Michael Gertz: move static arrays out of header and into the one file that needs them
112  *
113  * Revision 6.70  2004/08/05 17:30:53  camacho
114  * Remove initialization of identifier as it is no longer required
115  *
116  * Revision 6.69  2004/07/24 18:56:01  camacho
117  * Fix in posDemographics when GetSequenceWithDenseSeg cannot find sequence data
118  *
119  * Revision 6.68  2004/07/19 17:13:13  papadopo
120  * add capability to perform input and output of residue frequencies in scoremat form; also call PSIMatrixFrequencyRatiosNew before restarting from checkpoint
121  *
122  * Revision 6.67  2004/07/13 13:54:15  camacho
123  * Fix memory leak
124  *
125  * Revision 6.66  2004/06/25 21:54:51  dondosha
126  * Choose ideal values for lambda and K correctly for ungapped search
127  *
128  * Revision 6.65  2004/06/23 14:53:29  camacho
129  * Copy renamed versions of SFreqRatios and its *{New,Free} functions to avoid
130  * dependency ncbitool -> blast
131  *
132  * Revision 6.64  2004/06/22 14:16:46  camacho
133  * Changed signature of posFreqsToMatrix, added use of SFreqRatios structure from
134  * algo/blast/core/ to obtain underlying matrices' frequency ratios.
135  * This change results in using the frequency ratios to provide the scores
136  * for the PSSM in columns where all residue frequencies are 0. Previously the
137  * standard scoring matrix were used.
138  *
139  * Revision 6.63  2004/06/08 14:03:48  camacho
140  * Alejandro Schaffer's fix to spread out gap costs in posDemographics.
141  *
142  * Revision 6.62  2004/05/14 12:13:09  camacho
143  * Made posDemographics non-static for testing purposes.
144  *
145  * Revision 6.61  2003/08/04 20:43:55  dondosha
146  * Test for selenocysteines when comparing checkpoint sequences with query
147  *
148  * Revision 6.60  2003/05/30 17:25:37  coulouri
149  * add rcsid
150  *
151  * Revision 6.59  2003/05/13 16:02:53  coulouri
152  * make ErrPostEx(SEV_FATAL, ...) exit with nonzero status
153  *
154  * Revision 6.58  2001/12/11 14:48:54  madden
155  * Fix for ABW (reset Xcount to zero in some cases)
156  *
157  * Revision 6.57  2001/08/29 19:04:48  madden
158  * added parameter posComputationCalled to outputPosComputation, extra printing added in revision 6.54 is suppressed if posComputationCalled is FALSE
159  *
160  * Revision 6.56  2001/08/06 18:09:13  madden
161  * Corrected handling of X in posCancel by adding usage of Xcount
162  *
163  * Revision 6.55  2001/04/09 13:00:09  madden
164  * Fixed error in posComputeExtents; adjustment of interval sizes when the query contained an X had been asymmetric.
165  *
166  * Revision 6.54  2001/04/03 19:38:24  madden
167  * Changed IDENTITY_PERCENTAGE to 0.94, Added to output of -Q option in outputPosMatrix
168  *
169  * Revision 6.53  2001/02/16 16:11:50  dondosha
170  * In WposComputation, compute posMatrix from posFreqs if seqalign argument is NULL
171  *
172  * Revision 6.52  2001/01/03 01:49:38  bauer
173  * Changed from static to "LIBCALL":
174  *  posAllocateMemory
175  *  posPurgeMatches
176  *  posCancel
177  *  posComputeExtents
178  *  posComputeSequenceWeights
179  *  posCheckWeights
180  *  posComputePseudoFreqs
181  *  posScaling
182  *
183  * Revision 6.51  2000/11/24 22:07:51  shavirin
184  * Fixed some memory leaks.
185  *
186  * Revision 6.50  2000/11/20 14:35:51  madden
187  * Changed FileOpen mode for byte-encoded checkpoint files from "r" to "rb" or from "w" to "wb" to solve a problem on Windows NT.
188  *
189  * Revision 6.49  2000/11/13 14:00:39  madden
190  * Added frequency ratios for * in all standard matrices
191  *
192  * Revision 6.48  2000/11/09 14:27:52  madden
193  * psi-blast fixes for star character
194  *
195  * Revision 6.47  2000/11/01 16:25:57  madden
196  * Changes from Futamura for psitblastn
197  *
198  * Revision 6.46  2000/10/24 16:28:29  madden
199  * Changed IDENTITY_RATIO for putging near-identical matches from 0.98 to 0.95
200  *
201  * Revision 6.45  2000/10/10 21:46:04  shavirin
202  * Added support for BLOSUM50, BLOSUM90, PAM250 with -t T
203  *
204  * Revision 6.44  2000/08/18 21:28:37  madden
205  * support for BLOSUM62_20A and BLOSUM62_20B
206  *
207  * Revision 6.43  2000/07/31 16:41:01  shavirin
208  * Reduced POSIT_SCALE_FACTOR from 1000 to 200 to avoid overflow
209  * with BLOSUM80; moved declaration os POSIT_SCALE_FACTOR to posit.h
210  *
211  * Revision 6.42  2000/07/26 13:11:19  shavirin
212  * Added magical "LIBCALL" to pacify Windows build function allocatePosFreqs()
213  *
214  * Revision 6.41  2000/07/25 18:12:04  shavirin
215  * WARNING: This is no-turning-back changed related to S&W Blast from
216  * Alejandro Schaffer
217  *
218  * Revision 6.40  2000/05/01 12:48:33  madden
219  * changed rules for gaps in processing alignments with -B
220  *
221  * Revision 6.39  2000/03/02 21:47:07  shavirin
222  * Added missing variable for POSIT_DEBUG case
223  *
224  * Revision 6.38  1999/12/16 19:18:00  egorov
225  * Code cleanup
226  *
227  * Revision 6.37  1999/11/16 21:33:46  shavirin
228  * Fixed bug involved posSearch->posResultSequences structure.
229  *
230  * Revision 6.36  1999/11/16 17:30:41  shavirin
231  * Added copying use_best_align parameter in copySearchItems.
232  *
233  * Revision 6.35  1999/11/15 22:21:09  shavirin
234  * Removed nested comments in log space.
235  *
236  * Revision 6.34  1999/11/15 21:48:31  shavirin
237  * Added possibility to take into account best alignments of all
238  * alignments (even with e-thresh value larger than threshhold)
239  *
240  * Revision 6.33  1999/10/21 16:15:04  shavirin
241  * Removed unused array and all references to array threshSequences
242  *
243  * Revision 6.32  1999/09/30 14:15:29  shavirin
244  * Fixed bug in the function findThreshSequences().
245  *
246  * Revision 6.31  1999/09/23 20:58:37  shavirin
247  * Fixed some memory leaks.
248  *
249  * Revision 6.27  1999/09/03 17:24:38  madden
250  * Eliminated use of posMaxThresh field in posSearchItems.  Recoded findThreshSequences completely and changed CposComputation so as not to use search->result_struct and thereby eliminate the hidden assumption that search->result_struct and listOfSeqAligns have the matches listed in the same order
251  *
252  * Revision 6.26  1999/08/04 13:27:10  madden
253  * Added -B option
254  *
255  * Revision 6.25  1999/04/05 14:45:40  madden
256  * Fixed format mismatches
257  *
258  * Revision 6.24  1999/03/21 19:41:51  madden
259  * Added 3rd argument matrixfp to outputPosMatrix, Took some of the code in outputPosMatrix outside the #ifdef POSIT_DEBUG for use with -Q option
260  *
261  * Revision 6.23  1999/01/26 18:27:58  madden
262  * Made functions public for AS
263  *
264  * Revision 6.22  1998/12/09 18:51:51  madden
265  * fixed counting bug in posCancel
266  *
267  * Revision 6.21  1998/09/28 12:31:31  madden
268  * Used BlastConstructErrorMessage
269  *
270  * Revision 6.20  1998/09/09 21:18:33  madden
271  * AS fixed warnings
272  *
273  * Revision 6.19  1998/09/09 16:09:20  madden
274  * Changes for PHI-BLAST
275  *
276  * Revision 6.18  1998/08/26 18:07:00  kans
277  * fixed -v -fd warnings (AS)
278  *
279  * Revision 6.17  1998/06/18 18:20:22  madden
280  * Fixed typo in posConvergenceTest
281  *
282  * Revision 6.16  1998/06/14 19:43:02  madden
283  * Added function posFreqsToInformation
284  *
285  * Revision 6.15  1998/06/12 20:38:48  madden
286  * Fix for no hits to build model situation
287  *
288  * Revision 6.14  1998/06/09 19:38:16  madden
289  * Changes rounddown to posit_rounddown to avoid conflict
290  *
291  * Revision 6.13  1998/04/24 19:29:30  madden
292  * Moved rescaling code to blastool.c
293  *
294  * Revision 6.12  1998/03/25 22:36:17  egorov
295  * Change type of posRepeatSequences
296  *
297  * Revision 6.11  1998/03/23 18:32:30  madden
298  * Fix for zero/zero problem
299  *
300  * Revision 6.10  1998/02/06 18:34:17  madden
301  * Added check that residue was not masked in posReadCheckpoint
302  *
303  * Revision 6.9  1998/02/03 15:57:28  madden
304  * Cpos arg in posComputePseudoFreqs set to FALSE for WposComputation call
305  *
306  * Revision 6.8  1998/01/02 22:19:46  madden
307  * Replaced printf by ErrPostEx of SEV_WARNING
308  *
309  * Revision 6.7  1997/12/23 21:07:06  madden
310  * Changes for checkpointing
311  *
312  * Revision 6.6  1997/12/12 22:14:35  kans
313  * changed round to rounddown to avoid CodeWarrior 68K collision
314  *
315  * Revision 6.5  1997/11/19 15:29:31  madden
316  * Changed OS_UNIX ifdef to POSIT_DEBUG
317  *
318  * Revision 6.4  1997/09/08 13:33:29  madden
319  * Added posEpsilon2 to check for small numbers
320  *
321  * Revision 6.3  1997/09/05 22:29:13  madden
322  * Check for zero denominator and replace log(2) by NCBIMATH_LN2
323  *
324  * Revision 6.2  1997/09/02 22:23:01  madden
325  * Removed redundant calls to updateLambdaK
326  *
327  * Revision 6.1  1997/08/27 21:18:18  madden
328  * Fixed problem with deleted matrix
329  *
330  * Revision 6.0  1997/08/25 18:53:48  madden
331  * Revision changed to 6.0
332  *
333  * Revision 1.22  1997/08/20 21:35:01  madden
334  * ALL_ROUNDS replaced by Boolean
335  *
336  * Revision 1.21  1997/08/11 15:45:24  madden
337  * eliminated obsolete fields
338  *
339  * Revision 1.20  1997/07/28 18:35:06  madden
340  * Removed and ifdefed printf
341  *
342  * Revision 1.19  1997/06/27 19:14:01  madden
343  * Fixed two bugs in posComputeSequenceWeights for the special case where all participating sequences are identical in a block
344  *
345  * Revision 1.17  1997/06/23 14:42:46  madden
346  *  Made posComputeSequenceWeights faster by catching the special case where the set of participating sequences does not change from one column to the next.
347  *
348  * Revision 1.16  1997/05/29 20:35:47  madden
349  * Eliminate duplicate sequences and alignments that are 98 perc. identical and ignore columns with all identical sequence weights.
350  *
351  * Revision 1.15  1997/05/27 20:26:09  madden
352  * Fixed problem with matrix
353  *
354  * Revision 1.14  1997/05/23 20:52:50  madden
355  * Fixed bug in setting of matrix for psi-blast
356  *
357  * Revision 1.13  1997/05/22 21:25:28  madden
358  * fixed memory leaks
359  *
360  * Revision 1.12  1997/05/16 20:56:35  madden
361  * replace hard coded numbers by defines
362  *
363  * Revision 1.11  1997/05/16 20:09:42  madden
364  * Fixes for statistical problems
365  *
366  * Revision 1.10  1997/05/07 21:00:03  madden
367  * Call to SeqId2OrdinalId replaces call to readdb_gi2seq
368  *
369  * Revision 1.9  1997/05/01 15:53:25  madden
370  * Addition of extra KarlinBlk's for psi-blast
371  *
372  * Revision 1.8  1997/04/23  13:31:20  madden
373  * Changed diagnostic output.
374  *
375  * Revision 1.7  1997/04/22  16:36:49  madden
376  * Changes for use of psi-blast with www.
377  *
378  * Revision 1.6  1997/04/10  19:25:53  madden
379  * Added casts, COMMAND_LINE replaced by ALL_ROUNDS.
380  *
381  * Revision 1.5  1997/04/09  20:01:53  madden
382  * Functions CposComputation and WposComputation replace posComputations.
383  *
384  * Revision 1.4  1997/04/04  20:44:55  madden
385  * Changed posComputation to return Int4Ptr *.
386  *
387  * Revision 1.3  1997/03/27  22:30:51  madden
388  * Fix for Array Bounds Read.
389  *
390  * Revision 1.2  1997/03/11  14:38:40  madden
391  * Fixes for GI's instead of ordinal numbers.
392  *
393  * Revision 1.1  1997/02/13  15:22:13  madden
394  * Initial revision
395  *
396 */
397 
398 
399 #include <ncbi.h>
400 #include <blastpri.h>
401 #include <objcode.h>
402 #include <objseq.h>
403 #include <objsset.h>
404 #include <objscoremat.h>
405 #include <sequtil.h>
406 #include <posit.h>
407 #include <txalign.h>
408 #include <blastkar.h>
409 
410 #include <algo/blast/composition_adjustment/nlm_linear_algebra.h>
411 #include <algo/blast/composition_adjustment/matrix_frequency_data.h>
412 #include <algo/blast/composition_adjustment/composition_adjustment.h>
413 #include <algo/blast/composition_adjustment/compo_heap.h>
414 #include <algo/blast/composition_adjustment/smith_waterman.h>
415 #include <algo/blast/composition_adjustment/redo_alignment.h>
416 #include <algo/blast/composition_adjustment/unified_pvalues.h>
417 
418 /*small constants to test against 0*/
419 #define posEpsilon 0.0001
420 #define posEpsilon2 0.0000001
421 /*Representation of a gap in a motif*/
422 #define GAP_CHAR 0
423 /*Used inside a seqAlign to reprsent the presence of a gap*/
424 #define GAP_HERE (-1)
425 /*Used to check that diagnostics printing routine will work*/
426 #define EFFECTIVE_ALPHABET 20
427 
428 #define POSIT_PERCENT 0.05
429 #define POSIT_NUM_ITERATIONS 10
430 
431 
432 #define POS_RESTING 0
433 #define POS_COUNTING 1
434 
435 #define IDENTITY_RATIO 0.94
436 
437 
438 /*Allocate memory for  data structures inside posSearch used in
439 * position-specific caculations
440 * posSearch -- to be filled in 
441 * alphabetSize -- number of distinct characters used in the sequences
442 * querySize -- number of characters in the query sequence
443 * numSequences -- number of matching sequences potentially in the model */
444 void LIBCALL posAllocateMemory(posSearchItems * posSearch, 
445                        Int4 alphabetSize, Int4 querySize, Int4 numSequences)
446 {
447   Int4 i, j;  /*loop indices*/
448 
449   posSearch->posCount = (Int4 *) MemNew(querySize * sizeof(Int4));
450   if (NULL == posSearch->posCount)
451     exit(EXIT_FAILURE);
452   for(i = 0; i < querySize; i++)
453     posSearch->posCount[i] = 0;
454 
455   posSearch->posC = (Int4 **) MemNew((querySize + 1) * sizeof(Int4 *));
456   if (NULL == posSearch->posC)
457     exit(EXIT_FAILURE);
458   for(i = 0; i <= querySize; i++) {
459     posSearch->posC[i] = (Int4 *) MemNew(alphabetSize * sizeof(Int4));
460     if (NULL == posSearch->posC[i])
461       exit(EXIT_FAILURE);   
462     for(j = 0; j < alphabetSize; j++)
463       posSearch->posC[i][j] = 0;
464  
465   }
466   posSearch->posDistinctDistrib = (Int4 **) MemNew((querySize + 1) * sizeof(Int4* ));
467   for (i = 0; i <=querySize; i++)  {
468     posSearch->posDistinctDistrib[i] = (Int4 *) MemNew((EFFECTIVE_ALPHABET + 1) * sizeof(Int4));
469     for(j = 0; j <=EFFECTIVE_ALPHABET; j++)
470       posSearch->posDistinctDistrib[i][j] = 0;
471   }
472   posSearch->posNumParticipating = (Int4 *) MemNew((querySize + 1) * sizeof(Int4 ));
473   posSearch->posGaplessColumnWeights = (Nlm_FloatHi *) MemNew((querySize + 1) * sizeof(Nlm_FloatHi));
474   if (NULL == posSearch->posGaplessColumnWeights)
475     exit(EXIT_FAILURE);
476   posSearch->posMatchWeights = (Nlm_FloatHi **) MemNew((querySize+1) * sizeof(Nlm_FloatHi *));
477   if (NULL == posSearch->posMatchWeights)
478     exit(EXIT_FAILURE);
479   for (i = 0; i <= querySize ; i++) {
480     posSearch->posMatchWeights[i] = (Nlm_FloatHi *) MemNew(alphabetSize * sizeof(Nlm_FloatHi));
481     if (NULL == posSearch->posMatchWeights[i])
482       exit(EXIT_FAILURE);
483     for(j = 0; j < alphabetSize; j++) 
484       posSearch->posMatchWeights[i][j] = 0.0;
485   }  
486 
487   posSearch->posMatrix = (BLAST_Score **) MemNew((querySize + 1) * sizeof(BLAST_Score *));
488   posSearch->posPrivateMatrix = (BLAST_Score **) MemNew((querySize + 1) * sizeof(BLAST_Score *));
489   if (NULL == posSearch->posMatrix)
490     exit(EXIT_FAILURE);
491   for(i = 0; i <= querySize; i++) {
492     posSearch->posMatrix[i] = (BLAST_Score *) MemNew(alphabetSize * sizeof(BLAST_Score));
493     posSearch->posPrivateMatrix[i] = (BLAST_Score *) MemNew(alphabetSize * sizeof(BLAST_Score));
494     if (NULL == posSearch->posMatrix[i])
495       exit(EXIT_FAILURE);   
496     for(j = 0; j < alphabetSize; j++)
497       posSearch->posMatrix[i][j] = 0;
498  
499   }
500 
501   posSearch->posSigma = (Nlm_FloatHi *) MemNew((querySize) * sizeof(Nlm_FloatHi));
502   if (NULL == posSearch->posSigma)
503     exit(EXIT_FAILURE);
504   for(i = 0; i < querySize; i++) {
505     posSearch->posSigma[i] = 0.0;
506   }
507 
508   posSearch->posIntervalSizes = (Int4 *) MemNew((querySize) * sizeof(Int4));
509   if (NULL == posSearch->posIntervalSizes)
510     exit(EXIT_FAILURE);
511   for(i=0; i < querySize; i++)
512     posSearch->posIntervalSizes[i] = 0;
513 
514   posSearch->posDescMatrixLength = numSequences;
515   posSearch->posDescMatrix = (posDesc **) MemNew((numSequences + 1) * sizeof(posDesc *));
516   if (NULL == posSearch->posDescMatrix)
517     exit(EXIT_FAILURE);
518   for (i = 0; i <= numSequences; i++) {
519     posSearch->posDescMatrix[i] = (posDesc *) MemNew(querySize * sizeof(posDesc));
520     if (NULL == posSearch->posDescMatrix[i])
521       exit(EXIT_FAILURE);
522     for(j = 0; j < querySize; j++) {
523       posSearch->posDescMatrix[i][j].letter = UNUSED;
524       posSearch->posDescMatrix[i][j].used = FALSE;
525       posSearch->posDescMatrix[i][j].e_value = 1.0;
526       posSearch->posDescMatrix[i][j].leftExtent = -1;
527       posSearch->posDescMatrix[i][j].rightExtent = querySize;
528     }
529   }  
530   posSearch->posExtents = (posDesc *) MemNew(querySize * sizeof(posDesc));
531   if (NULL == posSearch->posExtents)
532     exit(EXIT_FAILURE);
533   for(j = 0; j < querySize; j++) {
534     posSearch->posExtents[j].used = FALSE;
535     posSearch->posExtents[j].leftExtent = -1;
536     posSearch->posExtents[j].rightExtent = querySize;
537   }
538    posSearch->posA = (Nlm_FloatHi *) MemNew((numSequences+ 1) * sizeof(Nlm_FloatHi));
539    if (NULL == posSearch->posA)
540      exit(EXIT_FAILURE);
541    posSearch->posRowSigma = (Nlm_FloatHi *) MemNew((numSequences + 1) * sizeof(Nlm_FloatHi));
542    if (NULL == posSearch->posRowSigma)
543      exit(EXIT_FAILURE);
544 
545    /* populated in posComputePseudoFreqs or on demand */
546    posSearch->stdFreqRatios = NULL; 
547 }
548 
549 static void freePosFreqs(Nlm_FloatHi ** posFreqs, Int4 length)
550 {
551   Int4 i;
552 
553   for (i = 0; i <= length; i++)
554     MemFree(posFreqs[i]);
555   MemFree(posFreqs); 
556 }
557 
558 /*Deallocate memory allocated in posReadCheckpoint
559 * posSearch -- pointer to record used in building the position-specific model
560 * querySize -- number of characters in the query sequence
561 */
562 void LIBCALL posCheckpointFreeMemory(posSearchItems *posSearch, Int4 querySize)
563 {
564   Int4 i;  /*loop index*/
565 
566   freePosFreqs(posSearch->posFreqs, querySize);
567   for(i = 0; i <= querySize; i++){
568     MemFree(posSearch->posMatrix[i]);
569     MemFree(posSearch->posPrivateMatrix[i]);
570   }
571   MemFree(posSearch->posMatrix);
572   MemFree(posSearch->posPrivateMatrix);
573 }
574 
575 /*Deallocate memory allocated in posAllocateMemory
576 * posSearch -- pointer to record used in building the position-specific model
577 * querySize -- number of characters in the query sequence
578 */
579 static void posFreeMemory(posSearchItems *posSearch, Int4 querySize)
580 {
581   Int4 i;  /*loop index*/
582 
583   MemFree(posSearch->posCount);
584   MemFree(posSearch->posExtents);
585   MemFree(posSearch->posSigma);
586 
587   for(i = 0; i <= querySize; i++){
588     MemFree(posSearch->posC[i]);
589     MemFree(posSearch->posMatrix[i]);
590     MemFree(posSearch->posPrivateMatrix[i]);
591     MemFree(posSearch->posMatchWeights[i]);
592     MemFree(posSearch->posDistinctDistrib[i]);
593   }
594 
595   MemFree(posSearch->posC);
596   MemFree(posSearch->posDistinctDistrib);
597   MemFree(posSearch->posNumParticipating);
598 
599   for(i = 0; i <= posSearch->posDescMatrixLength; i++)
600     MemFree(posSearch->posDescMatrix[i]);
601 
602   MemFree(posSearch->posMatrix);
603   MemFree(posSearch->posPrivateMatrix);
604   MemFree(posSearch->posDescMatrix);
605   MemFree(posSearch->posGaplessColumnWeights);
606   MemFree(posSearch->posMatchWeights);
607   MemFree(posSearch->posA);
608   MemFree(posSearch->posRowSigma);
609   MemFree(posSearch->posIntervalSizes);
610   MemFree(posSearch->posUseSequences);
611   posSearch->stdFreqRatios = PSIMatrixFrequencyRatiosFree(posSearch->stdFreqRatios);
612   freePosFreqs(posSearch->posFreqs,querySize);
613 }
614 
615 /*Cleanup position-specific  data structures after one pass*/
616 void LIBCALL posCleanup(posSearchItems *posSearch, compactSearchItems * compactSearch)
617 {
618   posFreeMemory(posSearch, compactSearch->qlength);
619 }
620 
621 
622 /*extract the e-value that applies to an entire dense
623   diagonal alignment from its ScorePtr, based on similar
624   code from Tom Madden*/
625 
626 static Nlm_FloatHi getEvalueFromSeqAlign(SeqAlignPtr thisSeqAlign)
627 {
628   ScorePtr thisScorePtr;
629 
630   thisScorePtr = thisSeqAlign->score;
631   while ((thisScorePtr != NULL) &&
632          (StringICmp(thisScorePtr->id->str, "e_value") != 0) &&
633          (StringICmp(thisScorePtr->id->str, "sum_e") != 0))
634     thisScorePtr = thisScorePtr->next;
635   if(NULL == thisScorePtr)
636     return(10.0);
637   else
638     return((Nlm_FloatHi) (thisScorePtr->value.realvalue));
639 }
640 
641 /*Find the lowest e-value among all seqAligns for the sequence represented by
642 curSeqAlign*/
643 static Nlm_FloatHi minEvalueForSequence(SeqAlignPtr curSeqAlign, SeqAlignPtr listOfSeqAligns) 
644 {
645    SeqAlignPtr testSeqAlign; /*Index into listOfSeqALigns*/
646    DenseSegPtr curSegs, testSegs; /*Used to extract ids from curSeqAlign, testSeqAlign*/
647    SeqIdPtr curId, testId; /*Ids of target sequences in testSeqAlign*/
648    Nlm_FloatHi  returnValue; /*stores current best e-value*/
649    Nlm_FloatHi  testEvalue; /*temporary e-value for one seqAlign*/
650    Boolean seen;   /*have we seen a seqAlign matching the sequence yet*/
651 
652    returnValue = getEvalueFromSeqAlign(curSeqAlign);
653    curSegs = (DenseSegPtr) curSeqAlign->segs;
654    curId = curSegs->ids->next; 
655    seen = FALSE;
656 
657    testSeqAlign = listOfSeqAligns;
658    while (NULL != testSeqAlign) {
659      testSegs = (DenseSegPtr) testSeqAlign->segs;
660 
661      if(testSegs->ids == NULL)
662          break;
663 
664      testId = testSegs->ids->next; 
665      if (SeqIdMatch(curId, testId)) {
666          seen = TRUE;
667          if ((testEvalue = getEvalueFromSeqAlign(testSeqAlign)) < returnValue)
668            returnValue = testEvalue;
669        }
670      else
671       /*if we have already seen a match and this one doesn't match,
672         then stop looking*/
673        if (seen)  
674          break;
675      testSeqAlign = testSeqAlign->next;
676    }
677    return(returnValue);
678 }
679 
680 
681 /*Count the number of seqAligns in a list (returned) and count the number of
682 distinct target sequences represented (passed back in numSequences);
683 if useThreshold is TRUE, only those sequences with e-values below the threshold are counted.
684 Important assumption: All SeqAligns with  the same target sequence
685 are consecutive in the list*/
686 static Int4 countSeqAligns(SeqAlignPtr listOfSeqAligns, Int4 * numSequences, Boolean useThreshold, Nlm_FloatHi threshold)
687 {
688     SeqAlignPtr curSeqAlign, prevSeqAlign;
689     Int4 seqAlignCounter;
690     DenseSegPtr curSegs;
691     SeqIdPtr curId, prevId; /*Ids of target sequences in current and previous
692                               SeqAlign*/
693     
694     seqAlignCounter = 0;
695     *numSequences = 0;
696     curSeqAlign = listOfSeqAligns;
697     prevSeqAlign = NULL;
698     while (NULL != curSeqAlign) {
699         curSegs = (DenseSegPtr) curSeqAlign->segs;
700         if(curSegs->ids == NULL)
701             break;
702         curId = curSegs->ids->next; 
703         seqAlignCounter++;
704         if ((NULL == prevSeqAlign) ||  (!(SeqIdMatch(curId, prevId))))
705             if (!useThreshold || (threshold > minEvalueForSequence(curSeqAlign, listOfSeqAligns)))
706                 (*numSequences)++;
707         prevSeqAlign = curSeqAlign;
708         prevId = curId;
709         curSeqAlign = curSeqAlign->next;
710     }
711     return(seqAlignCounter);
712 }
713 
714 /*Find which sequences that match in the i-th pass have an e-value below
715   the specified threshold. These sequences will be used to make the
716   score matrix for the next pass*/
717 static void findThreshSequences(posSearchItems *posSearch, BlastSearchBlkPtr search, SeqAlignPtr listOfSeqAligns, Int4 numalign, Int4 numseq)
718 {
719 
720     Int4 alignIndex; /* indices for sequences and alignments*/
721     SeqAlignPtr curSeqAlign, prevSeqAlign; /* pointers into list of seqAligns*/
722     DenseSegPtr curSegs;  /*Item in list of seqAligns*/
723     SeqIdPtr thisId, prevId; /*Ids of target sequences in current and previous
724                                SeqAlign*/  
725     Nlm_FloatHi thisEvalue; /*Best E-value for current sequence*/
726     Int4 ordinalNumber; /*index of sequence within database*/
727     
728     /*Allocate boolean array to store values*/
729     posSearch->posResultSequences = (Int4 *) MemNew(numseq * sizeof(Int4));
730     posSearch->posResultsCounter = 0;
731 
732     curSeqAlign = listOfSeqAligns;
733     prevSeqAlign = NULL;
734     for(alignIndex = 0; alignIndex < numalign; alignIndex++) {
735         curSegs = (DenseSegPtr) curSeqAlign->segs;
736         thisId = curSegs->ids->next;
737         if ((NULL == prevSeqAlign) ||  (!(SeqIdMatch(thisId, prevId)))) {
738             thisEvalue = minEvalueForSequence(curSeqAlign, curSeqAlign);
739             thisId = curSegs->ids->next;  /*id of target sequence is second*/
740             /*Get ordinal ids of sequences in result*/
741             ordinalNumber = SeqId2OrdinalId(search->rdfp, thisId);
742             if(thisEvalue < (search->pbp->ethresh)) {
743                 posSearch->posResultSequences[posSearch->posResultsCounter] =
744                     ordinalNumber;
745                 posSearch->posResultsCounter++;
746             }
747         }
748         prevSeqAlign = curSeqAlign;
749         prevId = thisId;
750         curSeqAlign = curSeqAlign->next;
751     }
752 }
753 
754 
755 
756 /* Determines if  the search has converged from round to round.
757 *  Checks whether every new sequence found is in posSearch->posResultSequences.
758 *  Also sets up posSearch->posRepeatSequences, a boolean array that
759 *  indicates whether the sequence represented by the i-th new seqAlign is a repeat.
760 *  This is used in printing the sequences where they are
761 *  subdivided into two categories: sequences that were found previously
762 *  and new sequences.
763 *  posSearch is the data structure representing the parameters of the position-specific part
764 *  search represents the overall  BLAST search
765 *  listOfSeqAligns is one representation of the results of the current round.
766 *  If thissPassNum is 1, then it checks only to see that some sequence
767 * distinct from the query was found */
768 void LIBCALL posConvergenceTest(posSearchItems *posSearch, BlastSearchBlkPtr search, SeqAlignPtr listOfSeqAligns, Int4 thisPassNum)
769 {
770   Int4 numseq;   /*Number of sequences found*/
771   Int4 numalign; /* Number of items in listOfSeqAligns*/
772   Int4 oldSeqIndex; /*Ordinal number of a sequence in old results (previous round)*/
773   Int4 alignIndex; /*index into the list of seqAligns*/
774   Boolean found;  /*Have we found the new sequence on the old list?*/
775   SeqAlignPtr curSeqAlign, prevSeqAlign, startAlign; /* pointers into list of seqAligns*/
776   DenseSegPtr curSegs;  /*Item in list of seqAligns*/
777   SeqIdPtr thisId, prevId; /*Ids of target sequences in current and previous
778                            SeqAlign*/
779   Int4 ordinalNumber; /*Ordinal number of a sequence in the database*/
780   Nlm_FloatHi thisEvalue; /*lowest evalue from all seqAligns for a sequence*/
781   Int4 queryOffset, subjectOffset, retrievalOffset; /*offsets needed
782                                                     to make a match align*/
783   Int4 qplace, splace; /*index into query string and matching string*/
784   Uint1Ptr q,s; /*Pointers into query and matching string*/
785   Int4 queryLength; /*length of query*/
786   Int4 matchLength; /* length of match*/
787   Int4 subjectLength; /* length of a matching string*/
788   Int4 c;  /*index into a string*/
789   Int4 numsegs; /*number of segments in an alignment*/
790   Int4 startQ,startS; /*Indices into array of starting positions*/
791 
792 
793   numalign = countSeqAligns(listOfSeqAligns, &numseq, FALSE, 0.0);
794   search->posConverged = TRUE;
795   curSeqAlign = listOfSeqAligns;
796   if (thisPassNum > 1) {
797     posSearch->posRepeatSequences = (Int2Ptr) MemNew(numalign * sizeof(Int2));
798     prevSeqAlign = NULL;
799     for(alignIndex = 0; alignIndex < numalign; alignIndex++) {
800       posSearch->posRepeatSequences[alignIndex] = (Int2) 0;
801       curSegs = (DenseSegPtr) curSeqAlign->segs;
802       thisId = curSegs->ids->next; 
803       if ((NULL == prevSeqAlign) ||  (!(SeqIdMatch(thisId, prevId)))) {
804         startAlign = curSeqAlign;
805         thisEvalue = minEvalueForSequence(curSeqAlign, startAlign);
806         if (thisEvalue < search->pbp->ethresh) {    
807           /*Extract the ordinal number from the SeqAlign*/
808           curSegs = (DenseSegPtr) curSeqAlign->segs;
809           thisId = curSegs->ids->next;  /*id of target sequence is second*/
810           /*Get ordinal ids of sequences in result*/
811           ordinalNumber = SeqId2OrdinalId(search->rdfp, thisId);
812           found = FALSE;
813           for(oldSeqIndex = 0; oldSeqIndex < posSearch->posResultsCounter; oldSeqIndex++)
814             if(ordinalNumber ==  posSearch->posResultSequences[oldSeqIndex]) {
815               posSearch->posRepeatSequences[alignIndex] = SEQ_ALIGN_MARK_REPEAT;
816               found = TRUE;
817               break;
818             }      
819           if (!found) 
820             search->posConverged = FALSE;
821         }
822       }
823       else  /*both alignments come from the same sequence*/
824         posSearch->posRepeatSequences[alignIndex] = posSearch->posRepeatSequences[alignIndex - 1];
825       prevSeqAlign = curSeqAlign;
826       prevId = thisId;
827       curSeqAlign = curSeqAlign->next;
828     }
829     MemFree(posSearch->posResultSequences);
830   }
831   else {
832     q = search->context[0].query->sequence;
833     queryLength = search->context[0].query->length;
834     prevSeqAlign = NULL;
835     while (curSeqAlign != NULL) {
836       curSegs = (DenseSegPtr) curSeqAlign->segs;
837       s = GetSequenceWithDenseSeg(curSegs, FALSE, &retrievalOffset, &subjectLength);
838       numsegs = curSegs->numseg;
839       thisId = curSegs->ids->next; 
840       if ((NULL == prevSeqAlign) ||  (!(SeqIdMatch(thisId, prevId)))) {
841         startAlign = curSeqAlign;
842         thisEvalue = minEvalueForSequence(curSeqAlign, startAlign);
843         if (thisEvalue < search->pbp->ethresh) {    
844           if (numsegs > 1) {
845             search->posConverged = FALSE;
846             return;
847           }
848           startQ = 0;
849           startS = 1;
850           queryOffset = curSegs->starts[startQ];
851           if (curSegs->starts[startS] != GAP_HERE)
852             subjectOffset = curSegs->starts[startS] - retrievalOffset;
853           else
854             subjectOffset = GAP_HERE;
855           matchLength = curSegs->lens[0];
856           if ((queryOffset != 0) || (subjectOffset != 0) ||
857               (matchLength != queryLength) || (matchLength != subjectLength)) {
858             search->posConverged = FALSE;
859             return;
860           }
861           for (c = 0, qplace = queryOffset, splace = subjectOffset;
862                c < matchLength; c++, qplace++, splace++)
863             if (s[splace] != q[qplace]) {
864               search->posConverged = FALSE;
865               return;
866             }        
867         }
868       }
869       prevSeqAlign = curSeqAlign;
870       prevId = thisId;
871       curSeqAlign = curSeqAlign->next;
872     }
873   }
874 }
875 
876 
877 /*Eliminate the matches from sequence second starting at position
878 matchStart and extending for intervalLength characters */
879 void LIBCALL posCancel(posSearchItems *posSearch, compactSearchItems * compactSearch, Int4 first, Int4 second, Int4 matchStart, Int4 intervalLength)
880 {
881   Int4 c, i;
882   Boolean stillNeeded;
883 
884   for(c = matchStart, i = 0; i < intervalLength; i++, c++) {
885     posSearch->posDescMatrix[second][c].used = FALSE;
886     posSearch->posDescMatrix[second][c].letter = 0;
887   }
888   stillNeeded = FALSE;
889   for (c = 0; c < compactSearch->qlength; c++)
890     if (posSearch->posDescMatrix[second][c].used) {
891       stillNeeded = TRUE;
892       break;
893     }
894    if (!stillNeeded)
895       posSearch->posUseSequences[second] = FALSE;
896 }
897 
898 /*Eliminate sequences that are identical to the query and partial alignments
899   that are identical in two matching sequences
900   Modified by Natsuhiko Futamura to change order in which
901   pairs of sequences are compared*/
902 void LIBCALL posPurgeMatches(posSearchItems *posSearch, compactSearchItems * compactSearch, ValNodePtr * error_return)
903 {
904   Int4 i, j; /*index over sequences*/
905   Int4 k; /*difference between pair of sequence indices*/
906   Boolean matchesQuery; /*Is a matching sequence identical to the query?*/
907   Int4 c; /*index over demographics of matching sequence*/
908   Int4 state; /*state of checking for a match*/
909   Int4 intervalLength, matchStart; /*Length and start of a matching region*/
910   Int4 matchNumber; /*number of characters matching*/
911   Int4 Xcount; /*number of X's in interval*/
912   Int4 numSequencesInUse; /*number of sequences left in use*/
913 
914   posSearch->posUseSequences =  (Boolean *) MemNew((posSearch->posNumSequences + 1) * sizeof(Boolean));
915    if (NULL == posSearch->posUseSequences)
916      exit(EXIT_FAILURE);
917   for(i = 0; i <= posSearch->posNumSequences; i++)
918     posSearch->posUseSequences[i] = TRUE;
919   for(i = 1; i <= posSearch->posNumSequences; i++) {
920     matchesQuery = TRUE;
921     for (c = 0; c < compactSearch->qlength; c++) {
922       if ((!posSearch->posDescMatrix[i][c].used) ||
923           (posSearch->posDescMatrix[i][c].letter !=
924            posSearch->posDescMatrix[0][c].letter)) {
925         matchesQuery = FALSE;
926         break;
927       }
928     }
929     if (matchesQuery) {
930       posSearch->posUseSequences[i] = FALSE;
931     }
932   }
933   for(j = 1; j <= posSearch->posNumSequences; j++) {
934     if (!posSearch->posUseSequences[j])
935       continue;
936     state = POS_COUNTING;
937     c = 0;
938     matchStart = 0;
939     intervalLength = 0;
940     Xcount = 0;
941     matchNumber = 0;
942     while (c < compactSearch->qlength) {
943       if (posSearch->posDescMatrix[j][c].used) {
944         if ((posSearch->posDescMatrix[0][c].letter != Xchar) &&
945             (posSearch->posDescMatrix[j][c].letter != Xchar)) { 
946           if (state == POS_RESTING) {
947             matchStart = c;
948             intervalLength = 1;
949             state = POS_COUNTING;
950             matchNumber = 0;
951           }
952           else 
953             intervalLength++;
954           if (posSearch->posDescMatrix[j][c].used &&
955               (posSearch->posDescMatrix[0][c].letter == posSearch->posDescMatrix[j][c].letter))
956             matchNumber++;
957         }
958         else {
959           if (POS_COUNTING == state)
960             Xcount++;
961         }
962       }
963       else {
964         if (state == POS_COUNTING) {
965           if ((intervalLength > 0) && (matchNumber == intervalLength))
966             posCancel(posSearch,compactSearch,0,j,matchStart,intervalLength+Xcount);
967           state = POS_RESTING;
968           Xcount = 0;
969         }
970       }
971       c++;
972     }
973     if (state == POS_COUNTING) /*at end of sequence i*/
974       if ((intervalLength > 0) && (matchNumber == intervalLength))
975         posCancel(posSearch,compactSearch,0,j,matchStart,intervalLength+Xcount);
976   }
977   
978   for (k=1; k <= posSearch->posNumSequences -1; k++){
979     for (i = 1; (i+k) <= posSearch->posNumSequences; i++) {
980       if (!posSearch->posUseSequences[i])
981         continue;
982       j = i+k;
983       if (!posSearch->posUseSequences[j])
984         continue;
985 
986       state = POS_COUNTING;
987       c = 0;
988       matchStart = 0;
989       intervalLength = 0;
990       Xcount = 0;
991       matchNumber = 0;
992       while (c < compactSearch->qlength) {
993         if (posSearch->posDescMatrix[i][c].used ||
994             posSearch->posDescMatrix[j][c].used) {
995           if ((posSearch->posDescMatrix[i][c].letter != Xchar) &&
996               (posSearch->posDescMatrix[j][c].letter != Xchar)) { 
997             if (state == POS_RESTING) {
998               matchStart = c;
999               intervalLength = 1;
1000               state = POS_COUNTING;
1001               matchNumber = 0;
1002             }
1003             else 
1004               intervalLength++;
1005             if (posSearch->posDescMatrix[i][c].used &&
1006                 posSearch->posDescMatrix[j][c].used &&
1007                 (posSearch->posDescMatrix[i][c].letter == posSearch->posDescMatrix[j][c].letter))
1008               matchNumber++;
1009           }
1010           else {
1011             if (POS_COUNTING == state)
1012               Xcount++;
1013           }
1014         }
1015         else {
1016           if (state == POS_COUNTING) {
1017             if ((intervalLength > 0) && ((((Nlm_FloatHi) matchNumber)/intervalLength) >= IDENTITY_RATIO))
1018               posCancel(posSearch,compactSearch,i,j,matchStart,intervalLength+Xcount);
1019             state = POS_RESTING;
1020             Xcount = 0;
1021           }
1022         }
1023         c++;
1024       }
1025       if (state == POS_COUNTING) /*at end of sequence i*/
1026         if ((intervalLength > 0) && ((((Nlm_FloatHi) matchNumber)/intervalLength) >= IDENTITY_RATIO))
1027           posCancel(posSearch,compactSearch,i,j,matchStart,intervalLength+Xcount);
1028     }
1029   }
1030   if (error_return) {
1031     numSequencesInUse = 0;
1032     for(i = 0; i <= posSearch->posNumSequences; i++)
1033       if(posSearch->posUseSequences[i])
1034         numSequencesInUse++;
1035     if (numSequencesInUse < 2)
1036       BlastConstructErrorMessage("posPurgeMatches", "Due to purging near identical sequences, only the query is used to construct the position-specific score matrix\n", 1, error_return);
1037   }
1038 }
1039 
1040 static void countNumSeq(posSearchItems *posSearch,
1041                   compactSearchItems * compactSearch,
1042                   SeqAlignPtr listOfSeqAligns, Int4 *prevNumSeq)
1043 {       
1044    Uint1Ptr s; /* pointer into a matching string */
1045    Int4  subjectLength;  /* length of subject */
1046    Int4  retrievalOffset;   /* retrieval offset */
1047    SeqAlignPtr curSeqAlign, prevSeqAlign; /* pointers into listOfSeqAligns */
1048    DenseSegPtr curSegs, prevSegs;  /* used to extract alignments from curSeqAlign */
1049    SeqIdPtr curId, prevId;  /* Used to compare sequences that come from different SeqAligns */
1050    Nlm_FloatHi thisEvalue;  /* evalue of current partial alignment */
1051    Int4 newNumSeq; /* numseq computed in another way */
1052    Boolean is_new_id = FALSE;   
1053 
1054    newNumSeq = 0;
1055    /*use only those sequences below e-value threshold*/
1056    curSeqAlign = listOfSeqAligns;
1057    prevSeqAlign = NULL;
1058    for (curSeqAlign = listOfSeqAligns; curSeqAlign != NULL;
1059                             curSeqAlign = curSeqAlign->next) {
1060       is_new_id = FALSE;
1061       thisEvalue = getEvalueFromSeqAlign(curSeqAlign);
1062       curSegs = (DenseSegPtr) curSeqAlign->segs;
1063       if (NULL != prevSeqAlign) {
1064          prevSegs = (DenseSegPtr) prevSeqAlign->segs;
1065          if(curSegs->ids == NULL)
1066             break;
1067          curId = curSegs->ids->next;
1068          prevId = prevSegs->ids->next;
1069 
1070          if (!(SeqIdMatch(curId, prevId)))
1071             is_new_id = TRUE;
1072       }
1073       if (!(compactSearch->use_best_align && is_new_id)) {
1074          if (thisEvalue >= compactSearch->ethresh)
1075             continue;
1076       }
1077       if (is_new_id == TRUE)
1078          newNumSeq++;
1079       s = GetSequenceWithDenseSeg(curSegs, FALSE, &retrievalOffset, &subjectLength);
1080       SeqMgrFreeCache();
1081       if (s == NULL)
1082          continue;
1083       s = MemFree(s);
1084       prevSeqAlign = curSeqAlign;
1085    }
1086    newNumSeq++;
1087    /* numseq gets the highest number computed by both methods */
1088    if (newNumSeq > *prevNumSeq)
1089       *prevNumSeq = newNumSeq;
1090 }
1091 
1092 /*Compute general information about the sequences that matched on the
1093   i-th pass such as how many matched at each query position and what letter
1094   matched*/
1095 void LIBCALL posDemographics(posSearchItems *posSearch, 
1096                              compactSearchItems * compactSearch, 
1097                              SeqAlignPtr listOfSeqAligns)
1098 {
1099    Uint1Ptr q; /*pointers into query */
1100    Uint1Ptr s; /*pointer into a matching string */
1101    Int4 length, subjectLength;  /*length of query and subject*/
1102    Int4 c; /*index into a string*/
1103    Int4 numseq, numSeqAligns;  /*number of matching sequences and SeqAligns*/
1104    Int4 seqIndex;  /*index for the array of matching sequences*/
1105    Int4 matchLength; /*length of a match*/
1106    Int4  queryOffset, subjectOffset, retrievalOffset;  /*offsets needed to make a match align*/
1107    Int4 qplace, splace; /*index into query string and matching string*/
1108    SeqAlignPtr curSeqAlign, prevSeqAlign; /*pointers into listOfSeqAligns*/
1109    DenseSegPtr curSegs, prevSegs;  /*used to extract alignments from curSeqAlign*/
1110    SeqIdPtr curId, prevId;  /*Used to compare sequences that come from different SeqAligns*/
1111    Int4 startQ, startS; /*Indices into array of starting positions*/
1112    Int4 numsegs; /*Number of pieces in the gapped alignment*/
1113    Int4 segIndex; /*Index for which piece we are at*/
1114    Nlm_FloatHi thisEvalue;  /*evalue of current partial alignment*/
1115    Boolean is_new_id = FALSE;
1116 
1117    q = compactSearch->query;
1118    length = compactSearch->qlength;
1119    for(c = 0; c < length; c++) {
1120      posSearch->posDescMatrix[0][c].letter = (Int1) q[c];
1121      posSearch->posDescMatrix[0][c].used = TRUE;
1122      posSearch->posDescMatrix[0][c].leftExtent = 0;
1123      posSearch->posDescMatrix[0][c].rightExtent = length;
1124      posSearch->posDescMatrix[0][c].e_value = compactSearch->ethresh/2;
1125      posSearch->posC[c][q[c]]++;
1126      posSearch->posCount[c]++;
1127    }
1128 
1129    numSeqAligns = countSeqAligns(listOfSeqAligns, &numseq, 
1130                                  !compactSearch->use_best_align, 
1131                                  compactSearch->ethresh);
1132    
1133    posSearch->posNumSequences = numseq;
1134    /*use only those sequences below e-value threshold*/
1135    seqIndex = 0;
1136    curSeqAlign = listOfSeqAligns;
1137    prevSeqAlign = NULL;
1138    for(curSeqAlign = listOfSeqAligns; curSeqAlign != NULL; 
1139        curSeqAlign = curSeqAlign->next) {
1140        is_new_id = FALSE;
1141 
1142        thisEvalue = getEvalueFromSeqAlign(curSeqAlign);
1143 
1144        curSegs = (DenseSegPtr) curSeqAlign->segs;
1145        if (NULL != prevSeqAlign) {
1146            prevSegs = (DenseSegPtr) prevSeqAlign->segs;
1147            
1148            if(curSegs->ids == NULL) 
1149                break;
1150            
1151            curId = curSegs->ids->next; 
1152            prevId = prevSegs->ids->next;
1153            if (!(SeqIdMatch(curId, prevId)))
1154                is_new_id = TRUE;
1155        }
1156        
1157        if(!(compactSearch->use_best_align && is_new_id)) { 
1158            if (thisEvalue >= compactSearch->ethresh)
1159                continue;
1160        }
1161        
1162        if(is_new_id == TRUE)
1163            seqIndex++;
1164        
1165        s = GetSequenceWithDenseSeg(curSegs, FALSE, &retrievalOffset, &subjectLength);
1166        if (s == NULL) {
1167            /* Kludge: set all of this sequence's residues to those of the query
1168             * so that it can be purged in posPurgeMatches */
1169            for (c = 0; c < length; c++) {
1170                posSearch->posDescMatrix[seqIndex+1][c].letter = (Int1) q[c];
1171                posSearch->posDescMatrix[seqIndex+1][c].used = TRUE;
1172                posSearch->posDescMatrix[seqIndex+1][c].e_value =
1173                    compactSearch->ethresh/2;
1174            }
1175            continue;
1176        }
1177        startQ = 0;
1178        startS = 1;
1179        numsegs = curSegs->numseg;
1180        for(segIndex = 0; segIndex < numsegs; segIndex++) {
1181            queryOffset = curSegs->starts[startQ];
1182            if (curSegs->starts[startS] != GAP_HERE) /*XX*/
1183                subjectOffset = curSegs->starts[startS] - retrievalOffset;
1184            else
1185                subjectOffset = GAP_HERE;
1186            matchLength = curSegs->lens[segIndex];
1187            if ((GAP_HERE ) == queryOffset) {
1188                ; /*do nothing, gap in query*/
1189            }
1190            else
1191              if ((GAP_HERE) == subjectOffset) { /*XX*/
1192                    for(c = 0, qplace = queryOffset;
1193                        c < matchLength; c++, qplace++) {
1194                      /*Keep the following test if spreading out gap costs, 
1195                        so that in that case a lower E-value non-gap trumps
1196                        a higher E-value gap; if not spreading out gap costs
1197                        then comment out the test, so that a higher E-value
1198                        gap trumps a lower E-value letter*/
1199                      if (!posSearch->posDescMatrix[seqIndex+1][qplace].used)
1200                        {
1201                          posSearch->posDescMatrix[seqIndex + 1][qplace].used = TRUE;
1202                          posSearch->posDescMatrix[seqIndex + 1][qplace].letter = GAP_CHAR;
1203                          posSearch->posDescMatrix[seqIndex + 1][qplace].e_value = 1.0;
1204                        }
1205                    }
1206                }
1207                else {  /*no gap*/
1208                    for(c = 0, qplace = queryOffset, splace = subjectOffset;
1209                        c < matchLength; c++, qplace++, splace++) {
1210                      if (!posSearch->posDescMatrix[seqIndex+1][qplace].used)
1211                        {
1212                          posSearch->posDescMatrix[seqIndex+1][qplace].letter = (Int1) s[splace]; 
1213                          posSearch->posDescMatrix[seqIndex+1][qplace].used = TRUE; 
1214                          posSearch->posDescMatrix[seqIndex+1][qplace].e_value = 
1215                            thisEvalue;
1216                        }
1217                    }
1218                }
1219            startQ += 2;
1220            startS += 2;
1221        }
1222        prevSeqAlign = curSeqAlign;
1223        s = MemFree(s);
1224    } /*closes the for loop over seqAligns*/
1225 }
1226 
1227 void LIBCALL posComputeExtents(posSearchItems *posSearch, compactSearchItems * compactSearch)
1228 {
1229    Int4 seqIndex; /*index of sequence*/
1230    Int4 length; /*length of query*/
1231    Int4 qplace, qplace2; /*place in query*/
1232    Int4 numseq; /*number of sequences including query*/
1233    Uint1Ptr q; /*pointers into query */
1234 
1235    length = compactSearch->qlength;
1236    numseq = posSearch->posNumSequences;
1237    q = compactSearch->query;
1238    for(seqIndex = 0; seqIndex < numseq; seqIndex++) {
1239      if (!posSearch->posUseSequences[seqIndex+1])
1240        continue; /*XX*/
1241      if ((posSearch->posDescMatrix[seqIndex+1][0].used) 
1242          && (posSearch->posDescMatrix[seqIndex+1][0].letter != GAP_CHAR))
1243        posSearch->posDescMatrix[seqIndex+1][0].leftExtent = 0;
1244      for(qplace = 1; qplace < length; qplace++)
1245        if(posSearch->posDescMatrix[seqIndex+1][qplace].used) {
1246          if(posSearch->posDescMatrix[seqIndex+1][qplace-1].used)
1247            posSearch->posDescMatrix[seqIndex+1][qplace].leftExtent =
1248              posSearch->posDescMatrix[seqIndex+1][qplace -1].leftExtent;
1249          else
1250            posSearch->posDescMatrix[seqIndex+1][qplace].leftExtent = qplace;
1251        } 
1252      if ((posSearch->posDescMatrix[seqIndex+1][length-1].used)
1253          && (posSearch->posDescMatrix[seqIndex+1][length-1].letter != GAP_CHAR))
1254        posSearch->posDescMatrix[seqIndex+1][length-1].rightExtent = length -1;
1255      for(qplace = length -2; qplace >= 0; qplace--)
1256        if(posSearch->posDescMatrix[seqIndex+1][qplace].used) {
1257          if(posSearch->posDescMatrix[seqIndex+1][qplace+1].used)
1258            posSearch->posDescMatrix[seqIndex+1][qplace].rightExtent =
1259              posSearch->posDescMatrix[seqIndex+1][qplace + 1].rightExtent;
1260          else
1261            posSearch->posDescMatrix[seqIndex+1][qplace].rightExtent = qplace;
1262        }
1263      for(qplace = 0; qplace < length; qplace++) 
1264        if (posSearch->posDescMatrix[seqIndex+1][qplace].used) {
1265          /* comment next if out to spread gap costs*/
1266          /* if (posSearch->posDescMatrix[seqIndex+1][qplace].letter != GAP_CHAR) { */
1267            posSearch->posExtents[qplace].leftExtent = MAX(posSearch->posExtents[qplace].leftExtent,
1268                                                         posSearch->posDescMatrix[seqIndex+1][qplace].leftExtent);
1269            posSearch->posExtents[qplace].rightExtent = MIN(posSearch->posExtents[qplace].rightExtent,
1270                                                            posSearch->posDescMatrix[seqIndex+1][qplace].rightExtent);
1271          
1272          }
1273      /*}*/ /*comment this out if we want to spread gap costs out */
1274 
1275      for(qplace = 0; qplace < length; qplace++) 
1276        /*used to check qplace for GAP_CHAR here*/ /*XX*/
1277        if (posSearch->posDescMatrix[seqIndex+1][qplace].used) {
1278          posSearch->posC[qplace][posSearch->posDescMatrix[seqIndex+1][qplace].letter]++;
1279          posSearch->posCount[qplace]++; /*Add to number of matches in this query position*/
1280        }
1281    }
1282    for(qplace = 0; qplace < length; qplace++)
1283      posSearch->posIntervalSizes[qplace] = posSearch->posExtents[qplace].rightExtent - 
1284        posSearch->posExtents[qplace].leftExtent + 1;
1285    for(qplace =0; qplace < length; qplace++) {
1286      if(Xchar == q[qplace]) {
1287        posSearch->posIntervalSizes[qplace] = 0;
1288        for(qplace2 = 0; qplace2 <qplace; qplace2++) {
1289          if((Xchar != q[qplace2]) && (posSearch->posExtents[qplace2].rightExtent >= qplace))
1290            posSearch->posIntervalSizes[qplace2]--;
1291        }
1292        for(qplace2 = length-1; qplace2 > qplace; qplace2--) {
1293          if((Xchar != q[qplace2]) && (posSearch->posExtents[qplace2].leftExtent <= qplace))
1294            posSearch->posIntervalSizes[qplace2]--;
1295        }
1296      }
1297    }
1298 }
1299  
1300 /*Compute weight of each sequence and letter in each position*/
1301 void LIBCALL posComputeSequenceWeights(posSearchItems *posSearch, compactSearchItems * compactSearch, Nlm_FloatHi weightExponent)
1302 {
1303    Int4 length; /*length of query*/
1304    Int4 numseq, seqIndex; /*number of matches, index for them*/
1305    Int4  i; /*index over a multi-alignment block*/
1306    Int4 qplace; /*index into query*/
1307    Nlm_FloatHi Sigma; /*Number of different characters occurring in matches within
1308                    a multi-alignment block, excluding identical columns*/
1309    Nlm_FloatHi intervalSigma; /*Same as Sigma but includes identical columns*/
1310    Int4 alphabetSize; /*number of characters in alphabet*/
1311    Int4 *participatingSequences; /*array of participating sequences at a position*/
1312    Int4 *oldParticipatingSequences; /*array of participating sequences at a position*/
1313    Int4 posLocalVariety;  /*number of different characters at a position*/
1314    Int4 posLocalStandardLet; /*posLocalVariety, not counting X or gap*/
1315    Int4 *posLocalC; /*counts of how many of each letter in this column*/
1316    Int4 c;
1317    Int4 thisSeq;
1318    Int4 numParticipating; /*number of sequences in this alignment block*/
1319    Int4 oldNumParticipating; /*number of sequences in this alignment block*/
1320    Boolean newSequenceSet; 
1321    Int4 p; /*index on sequences*/
1322    Nlm_FloatHi weightSum; /*Sum of intermediate sequence weights in a column 
1323                             used to normalize the weights, so they sum to 1*/
1324 
1325    alphabetSize = compactSearch->alphabetSize;
1326    length = compactSearch->qlength;
1327    numseq = posSearch->posNumSequences;
1328    participatingSequences = (Int4 *) MemNew((numseq+1) * sizeof(Int4));
1329    if (NULL == participatingSequences)
1330      exit(EXIT_FAILURE);
1331    oldParticipatingSequences = (Int4 *) MemNew((numseq+1) * sizeof(Int4));
1332    if (NULL == oldParticipatingSequences)
1333      exit(EXIT_FAILURE);
1334    posLocalC = (Int4 *) MemNew(alphabetSize * sizeof(Int4));
1335    if (NULL == posLocalC)
1336      exit(EXIT_FAILURE);
1337    for (qplace = 0; qplace < length; qplace++) {
1338      posSearch->posSigma[qplace] = 0.0;
1339    }
1340    numParticipating = 0;
1341    for(qplace = 0; qplace < length; qplace++) {
1342      posSearch->posGaplessColumnWeights[qplace] = 0.0;
1343      if ((posSearch->posCount[qplace] > 1) && (posSearch->posIntervalSizes[qplace] > 0)) {
1344        oldNumParticipating = numParticipating;
1345        for(p =0; p < numParticipating; p++)
1346          oldParticipatingSequences[p] = participatingSequences[p];
1347        numParticipating = 0;
1348        for (seqIndex = 0; seqIndex <= numseq; seqIndex++) {
1349          if (!posSearch->posUseSequences[seqIndex])
1350            continue; 
1351          /* if ((posSearch->posDescMatrix[seqIndex][qplace].used) &&
1352              (posSearch->posDescMatrix[seqIndex][qplace].letter != GAP_CHAR)) {
1353          */
1354          /*change to this if we want to spread gap costs*/
1355          if (posSearch->posDescMatrix[seqIndex][qplace].used) {
1356              participatingSequences[numParticipating] = seqIndex; 
1357            numParticipating++;
1358          }
1359        }
1360        newSequenceSet = TRUE;
1361        if (numParticipating == oldNumParticipating) {
1362          for(p = 0; p < numParticipating; p++)
1363            if (oldParticipatingSequences[p] != participatingSequences[p])
1364              break;
1365          if (p == numParticipating)
1366            newSequenceSet = FALSE;
1367        }
1368          
1369        if (newSequenceSet) {
1370          Sigma = 0;
1371          intervalSigma = 0;
1372          for (seqIndex = 0; seqIndex <= numseq; seqIndex++) {
1373            if (!posSearch->posUseSequences[seqIndex])
1374              continue;
1375            posSearch->posRowSigma[seqIndex] = 0.0;
1376            posSearch->posA[seqIndex] = 0.0;
1377          }
1378          for (i = posSearch->posExtents[qplace].leftExtent;
1379               i <= posSearch->posExtents[qplace].rightExtent; i++) {
1380            posLocalVariety = 0;
1381            posLocalStandardLet = 0;
1382            for(c = 0; c < alphabetSize; c++)
1383              posLocalC[c] = 0;
1384            for(seqIndex = 0; seqIndex < numParticipating; seqIndex++) {
1385              thisSeq = participatingSequences[seqIndex];
1386              /*used to check for GAP here*/ /*XX*/
1387              if (0 == posLocalC[posSearch->posDescMatrix[thisSeq][i].letter]) {
1388                /*letter (not a gap) not seen before in this query pos.*/
1389                posLocalVariety++;  
1390                if ((GAP_CHAR != posSearch->posDescMatrix[thisSeq][i].letter)  &&
1391                  (Xchar != posSearch->posDescMatrix[thisSeq][i].letter))
1392                  posLocalStandardLet++;
1393              }
1394              posLocalC[posSearch->posDescMatrix[thisSeq][i].letter]++;
1395            }
1396            intervalSigma += posLocalVariety;
1397            posLocalStandardLet = MIN(posLocalStandardLet,EFFECTIVE_ALPHABET);
1398            posSearch->posDistinctDistrib[qplace][posLocalStandardLet]++;
1399            if (posLocalVariety > 1) {
1400              Sigma += posLocalVariety;
1401            }
1402            for(seqIndex = 0; seqIndex < numParticipating; seqIndex++) {
1403              thisSeq = participatingSequences[seqIndex];
1404              /*used to check for gap here*/
1405              posSearch->posRowSigma[thisSeq] += 
1406                 ( 1.0 / 
1407   (((Nlm_FloatHi) posLocalC[posSearch->posDescMatrix[thisSeq][i].letter])
1408     * posLocalVariety));
1409            }
1410          }
1411        }
1412        else {
1413          for (i = 0; i <= EFFECTIVE_ALPHABET; i++) {
1414            posSearch->posDistinctDistrib[qplace][i] = posSearch->posDistinctDistrib[qplace - 1][i];        
1415          }
1416        }         
1417        if (Sigma > 0) {
1418          weightSum = 0;
1419          for (seqIndex = 0; seqIndex < numParticipating; seqIndex++) {
1420            thisSeq = participatingSequences[seqIndex];
1421            posSearch->posA[thisSeq] = posSearch->posRowSigma[thisSeq]/
1422             (posSearch->posExtents[qplace].rightExtent -
1423                posSearch->posExtents[qplace].leftExtent +1);
1424            /*spread gap weight here*/
1425            posSearch->posA[thisSeq] = pow(posSearch->posA[thisSeq],
1426                                           weightExponent);
1427            weightSum += posSearch->posA[thisSeq];
1428          }
1429          for (seqIndex = 0; seqIndex < numParticipating; seqIndex++) {
1430            thisSeq = participatingSequences[seqIndex];
1431            posSearch->posA[thisSeq] = posSearch->posA[thisSeq]/weightSum;
1432          }
1433        }
1434        else {
1435          for (seqIndex = 0; seqIndex < numParticipating; seqIndex++) {
1436            thisSeq = participatingSequences[seqIndex];
1437            posSearch->posA[thisSeq] = ((Nlm_FloatHi) 1 / (Nlm_FloatHi) numParticipating);
1438          }
1439        }
1440        posSearch->posSigma[qplace] = intervalSigma;
1441        for (seqIndex = 0; seqIndex < numParticipating; seqIndex++) {
1442          thisSeq = participatingSequences[seqIndex];
1443          posSearch->posMatchWeights[qplace][posSearch->posDescMatrix[thisSeq][qplace].letter] += posSearch->posA[thisSeq];
1444          if(posSearch->posDescMatrix[thisSeq][qplace].letter)
1445            posSearch->posGaplessColumnWeights[qplace] += posSearch->posA[thisSeq]; 
1446        }
1447        posSearch->posNumParticipating[qplace] = numParticipating;
1448      }
1449    }
1450    MemFree(participatingSequences);
1451    MemFree(oldParticipatingSequences);
1452    MemFree(posLocalC);
1453 }
1454 
1455 static Nlm_FloatHi countsFunction(Nlm_FloatHi Sigma, Int4 intervalLength)
1456 {
1457   return(Sigma / intervalLength - 1);
1458 }
1459 
1460 #define MAX_IND_OBSERVATIONS  400
1461 
1462 
1463 /*initialize the expected number of observations
1464   use background probabilities for this matrix
1465   Calculate exp. # of distinct aa's as a function of independent trials   
1466 */ 
1467 static void initializeExpNumObservations(double *expno, 
1468                                     double *backgroundProbabilities)
1469 
1470 {
1471 int     j,k ; /*loop indices*/
1472 double  weighted_sum; /*20 - this is how many distinct
1473                          amino acids are expected*/
1474 
1475    expno[0] = 0;
1476    for (j=1;j<MAX_IND_OBSERVATIONS;++j) {
1477      weighted_sum = 0;
1478      for (k=0;k<EFFECTIVE_ALPHABET;++k) 
1479        weighted_sum += exp(j*log(1.0-backgroundProbabilities[k]));
1480      expno[j] = EFFECTIVE_ALPHABET-weighted_sum;
1481    }
1482 }
1483 
1484 
1485 /*A method to estimate the effetive number of observations
1486   in the interval for the specified columnNumber */
1487 
1488 static Nlm_FloatHi effectiveObservations(posSearchItems *posSearch, 
1489                                          Int4 columnNumber, Int4 queryLength,
1490                                          double *expno)
1491 {
1492 int     i,k; /*loop indices*/
1493 double  indep; /*number of independent observations to return*/
1494 int halfNumColumns; /*half the number of columns in the interval, rounded
1495                       down*/
1496 int totalDistinctCounts; /*total number of distinct letters in columns
1497                      used*/
1498 double aveDistinctAA; /*average number of distinct letters in columns used*/
1499 int columnsAccountedFor; /*how many of the columns had their
1500                             distinct count totaled so far*/
1501 
1502   
1503  if (posSearch->posExtents[columnNumber].leftExtent < 0)
1504    return(0);
1505  if (posSearch->posExtents[columnNumber].rightExtent >= queryLength)
1506    return(0);
1507  
1508 /*  Calculate the average number of distinct amino acids in the half of the
1509     columns within the block in question with the most distinct amino acids;
1510     +2 in the parentheses is for rounding up.*/
1511 
1512  halfNumColumns = MAX(1,(posSearch->posExtents[columnNumber].rightExtent -
1513                          posSearch->posExtents[columnNumber].leftExtent+2)/2);
1514  k = EFFECTIVE_ALPHABET;
1515  columnsAccountedFor = 0;
1516  totalDistinctCounts = 0;
1517  while (columnsAccountedFor < halfNumColumns) {
1518    totalDistinctCounts += (posSearch->posDistinctDistrib[columnNumber][k] *k);
1519    columnsAccountedFor += posSearch->posDistinctDistrib[columnNumber][k];
1520    if (columnsAccountedFor > halfNumColumns) {
1521      totalDistinctCounts -=
1522        ((columnsAccountedFor - halfNumColumns) * k);
1523      columnsAccountedFor = halfNumColumns;
1524    }
1525    k--;
1526  }
1527  aveDistinctAA = ((double) totalDistinctCounts)/
1528    ((double) columnsAccountedFor);
1529 
1530 /*    Then use the following code to calculate the number of
1531         independent observations corresponding to
1532         aveDistinctAA.
1533 */
1534 
1535  for (i=1;i<MAX_IND_OBSERVATIONS && expno[i]<=aveDistinctAA;++i);
1536  indep = (i==MAX_IND_OBSERVATIONS) ? i : 
1537    i-(expno[i]-aveDistinctAA)/(expno[i]-expno[i-1]);
1538  indep = MIN(indep, posSearch->posNumParticipating[columnNumber]);      
1539  indep = MAX(0,indep - 1);
1540  return(indep);
1541 }
1542 
1543 static Nlm_FloatHi posit_rounddown(Nlm_FloatHi value)
1544 {
1545   return (Nlm_FloatHi) Nlm_Nint(value);
1546 }
1547 
1548 /*check that weights add to 1 in each column */
1549 void LIBCALL posCheckWeights(posSearchItems *posSearch, compactSearchItems * compactSearch)
1550 {
1551    Uint1Ptr q;  /*pointer to query*/
1552    Int4 length, alphabetSize; /*length of query and number of characters in alphabet*/
1553    Int4  a, c; /*loop indices*/
1554    Nlm_FloatHi runningSum; /*partial total for a column*/
1555 
1556 
1557    length = compactSearch->qlength;
1558    alphabetSize = compactSearch->alphabetSize;
1559 
1560    q = compactSearch->query;
1561    for(c = 0; c < length; c++) {
1562      if ((posSearch->posCount[c] > 1) && (q[c] != Xchar)) {
1563        runningSum = 0;
1564        /*       if (posSearch->posMatchWeights[c][0] > 0.0)
1565                 printf("Stop here %d ", c); */
1566        for(a = 0; a < alphabetSize; a++) 
1567            runningSum += posSearch->posMatchWeights[c][a];
1568        if((runningSum < 0.99) || (runningSum > 1.01))
1569          ErrPostEx(SEV_ERROR, 0, 0, "\nERROR IN WEIGHTS, column %d, value %lf\n",c, runningSum);
1570        /* spread out gap weight here*/
1571        for(a = 1; a < alphabetSize; a++) 
1572          if (compactSearch->standardProb[a] > posEpsilon)
1573            posSearch->posMatchWeights[c][a] = posSearch->posMatchWeights[c][a] +
1574            (posSearch->posMatchWeights[c][0] * compactSearch->standardProb[a]);
1575        posSearch->posMatchWeights[c][0] = 0.0;
1576        runningSum = 0;
1577        for(a = 0; a < alphabetSize; a++) 
1578            runningSum += posSearch->posMatchWeights[c][a];
1579        if((runningSum < 0.99) || (runningSum > 1.01))
1580          ErrPostEx(SEV_ERROR, 0, 0, "\nERROR IN WEIGHTS, column %d, value %lf\n",c, runningSum);
1581      }
1582    }
1583 }
1584 
1585 /*Fill in information content per position from pseudo-count frequencies*/
1586 static void  posFreqsToInformation(posSearchItems * posSearch, compactSearchItems * compactSearch)
1587 {
1588    Int4 length;  /*length of the query*/
1589    Int4 c; /*loop index*/
1590    Int4 a, alphabetSize; /*loop index and size of alphabet*/
1591    Nlm_FloatHi  qOverPEstimate; /*intermediate term*/
1592    Nlm_FloatHi  infoSum; /*information content sum for this position*/
1593   
1594    length = compactSearch->qlength;
1595    alphabetSize = compactSearch->alphabetSize;
1596    for (c = 0; c < length; c++) {
1597      infoSum = 0;
1598      for(a = 0; a < alphabetSize; a++) {
1599        if (compactSearch->standardProb[a] > posEpsilon) {
1600          qOverPEstimate = posSearch->posFreqs[c][a] / compactSearch->standardProb[a];
1601          if (qOverPEstimate > posEpsilon)
1602            infoSum += posSearch->posFreqs[c][a] * log(qOverPEstimate)/
1603                     NCBIMATH_LN2;
1604        }
1605      }
1606      posSearch->posInformation[c] = infoSum;
1607    }
1608 }
1609 
1610 /*Convert pseudo-count frequencies to a score matrix, where standard
1611 matrix is represented by its frequencies */
1612 void LIBCALL posFreqsToMatrix(posSearchItems *posSearch, 
1613                               compactSearchItems *compactSearch)
1614 {
1615    Uint1Ptr q;  /*pointer to the query*/
1616    Int4 length;  /*length of the query*/
1617    Int4 c; /*loop index*/
1618    Int4 a, alphabetSize; /*loop index and size of alphabet*/
1619    Nlm_FloatHi lambda; /*Karlin-Altschul parameter*/
1620    Nlm_FloatHi  qOverPEstimate, value; /*intermediate terms*/
1621    Boolean allZeros; /*are all frequencies in a column 0?*/
1622    Nlm_FloatHi intermediateValue; /*intermediate value*/
1623 
1624    q = compactSearch->query;
1625    length = compactSearch->qlength;
1626 
1627    alphabetSize = compactSearch->alphabetSize;
1628    lambda = compactSearch->lambda_ideal;
1629 
1630 
1631    for(c = 0; c < length; c++) {
1632      allZeros = TRUE;
1633      for(a = 0; a < alphabetSize; a++) {
1634        /*Division compensates for multiplication in posComputePsedoFreqs*/
1635        if (compactSearch->standardProb[a] > posEpsilon)
1636          qOverPEstimate = posSearch->posFreqs[c][a]/compactSearch->standardProb[a];
1637        else
1638         qOverPEstimate = 0.0;
1639        if (qOverPEstimate != 0.0)
1640          allZeros = FALSE;
1641        if (0.0 == qOverPEstimate || (compactSearch->standardProb[a] < posEpsilon))
1642          posSearch->posPrivateMatrix[c][a] = BLAST_SCORE_MIN;
1643        else {
1644          value = log(qOverPEstimate)/lambda;
1645          posSearch->posPrivateMatrix[c][a] = (BLAST_Score) posit_rounddown(POSIT_SCALE_FACTOR*value);
1646 
1647        }
1648        if (((Xchar == a) || (StarChar == a)) && (compactSearch->matrix[q[c]][Xchar] != BLAST_SCORE_MIN))
1649          posSearch->posPrivateMatrix[c][a] = 
1650            compactSearch->matrix[q[c]][a] * POSIT_SCALE_FACTOR;
1651      }
1652      if (allZeros) {
1653        if ( !posSearch->stdFreqRatios ) {
1654          ErrPostEx(SEV_FATAL, 1, 0, "Frequency ratios for %s scoring matrix are not available\n", compactSearch->standardMatrixName);
1655          return;
1656        }
1657 
1658        for(a = 0; a < alphabetSize; a++) {
1659          posSearch->posMatrix[c][a] = compactSearch->matrix[q[c]][a];
1660          if (posSearch->stdFreqRatios->data[q[c]][a] == 0.0) {
1661            posSearch->posPrivateMatrix[c][a] = BLAST_SCORE_MIN;
1662          } else {
1663            intermediateValue = POSIT_SCALE_FACTOR *
1664              posSearch->stdFreqRatios->bit_scale_factor *
1665              log(posSearch->stdFreqRatios->data[q[c]][a])/NCBIMATH_LN2;
1666            posSearch->posPrivateMatrix[c][a] = Nlm_Nint(intermediateValue);
1667          }
1668        }
1669      }
1670    }
1671    for(a = 0; a < alphabetSize; a++) {
1672      posSearch->posPrivateMatrix[length][a] = posSearch->posPrivateMatrix[length][a] = BLAST_SCORE_MIN;
1673    }
1674 }
1675 
1676 /*copy position specific frequency matrix of diminesions qlength * alphabetSize*/
1677 void LIBCALL copyPosFreqs(Nlm_FloatHi **posFreqsFrom, Nlm_FloatHi **posFreqsTo, Int4 qlength, Int4 alphabetSize)
1678 {
1679   Int4 c, i; /*loop indices*/
1680 
1681   for (i = 0; i < qlength; i++)
1682     for (c = 0; c < alphabetSize; c++)
1683       posFreqsTo[i][c] = posFreqsFrom[i][c];
1684 }
1685 
1686 Nlm_FloatHi ** LIBCALL allocatePosFreqs(Int4 length, Int4 alphabetSize)
1687 {
1688   Int4 c, i; /*loop indices*/
1689   Nlm_FloatHi ** returnArray;
1690 
1691   returnArray = (Nlm_FloatHi **) MemNew((length + 1) * sizeof(Nlm_FloatHi *));
1692   if (NULL == returnArray)
1693     exit(EXIT_FAILURE);
1694   for(i = 0; i <= length; i++) {
1695     returnArray[i] = (Nlm_FloatHi *) MemNew(alphabetSize * sizeof(Nlm_FloatHi));
1696     if (NULL == returnArray[i])
1697       exit(EXIT_FAILURE);   
1698     for(c = 0; c < alphabetSize; c++)
1699       returnArray[i][c] = 0.0;
1700   }
1701   return(returnArray); 
1702 }
1703 
1704 /*The following constants are used in 
1705   posComputePseudoFreqs and columnSpecificPseudocounts */
1706 #define PSEUDO_MULTIPLIER 500
1707 #define PSEUDO_SMALL_INITIAL 5.5 /*small number of pseudocounts to
1708                                    avoid 0 probabilities in entropy-based
1709                                    method*/
1710 #define PSEUDO_NUMERATOR 0.0457  /*numerator of entropy-based method*/
1711 #define PSEUDO_EXPONENT 0.8  /*exponent of denominator*/
1712 #define PSEUDO_MAX 1000000 /*effective infinity*/
1713 #define ZERO_OBS_PSEUDO 30 /*arbitrary constant to use for columns with 
1714                              zero observations in actual data*/
1715 
1716 static void  fillColumnProbabilities(double *probabilities, 
1717                                      posSearchItems *posSearch, 
1718                                      Int4 columnNumber)
1719 {
1720    Int4 charOrder[EFFECTIVE_ALPHABET]; /*standard order of letters according to S. Altschul*/
1721    Int4 c; /*loop index*/
1722 
1723    charOrder[0] =  1;  /*A*/
1724    charOrder[1] =  16; /*R*/
1725    charOrder[2] =  13; /*N*/  
1726    charOrder[3] =  4;  /*D*/ 
1727    charOrder[4] =  3;  /*C*/
1728    charOrder[5] =  15; /*Q*/
1729    charOrder[6] =  5;  /*E*/ 
1730    charOrder[7] =  7;  /*G*/
1731    charOrder[8] =  8;  /*H*/
1732    charOrder[9] =  9;  /*I*/
1733    charOrder[10] = 11; /*L*/
1734    charOrder[11] = 10; /*K*/
1735    charOrder[12] = 12; /*M*/  
1736    charOrder[13] =  6; /*F*/
1737    charOrder[14] = 14; /*P*/
1738    charOrder[15] = 17; /*S*/
1739    charOrder[16] = 18; /*T*/
1740    charOrder[17] = 20; /*W*/
1741    charOrder[18] = 22; /*Y*/
1742    charOrder[19] = 19; /*V*/
1743 
1744    for(c = 0; c < EFFECTIVE_ALPHABET; c++) 
1745      probabilities[c] = posSearch->posMatchWeights[columnNumber][charOrder[c]];
1746 }
1747 
1748 /*adjust the probabilities by assigning observations weight
1749   to initialProbabilities and standardWeight to standardProbabilities*/
1750 static void adjustColumnProbabilities(double *initialProbabilities,
1751                                       double *probabilitiesToReturn,
1752                                       double standardWeight, 
1753                                       double *standardProbabilities, 
1754                                       double observations)
1755 {
1756   double intermediateSums[EFFECTIVE_ALPHABET]; /*weighted sums for each letter*/
1757   double overallSum; /*overall sum of weightedSums*/
1758   Int4 c; /*loop index*/
1759 
1760   overallSum = 0.0;
1761   for(c = 0; c < EFFECTIVE_ALPHABET; c++) {
1762     intermediateSums[c] =
1763       (initialProbabilities[c] * observations) +
1764       (standardProbabilities[c] * standardWeight);
1765     overallSum += intermediateSums[c];
1766   }
1767   for(c = 0; c < EFFECTIVE_ALPHABET; c++) 
1768     probabilitiesToReturn[c] = intermediateSums[c]/overallSum;
1769 }
1770 
1771 /*compute relative entropy of first distribution to second distribution*/
1772 
1773 static double computeRelativeEntropy(double *newDistribution,
1774                               double *backgroundProbabilities)
1775 {
1776    Int4 c; /*loop index*/
1777    double returnValue; /*value to return*/
1778    
1779 
1780    returnValue = 0;
1781    for(c = 0; c < EFFECTIVE_ALPHABET; c++) {
1782      if (newDistribution[c] > posEpsilon)
1783        returnValue += (newDistribution[c] * 
1784                        log (newDistribution[c]/backgroundProbabilities[c]));
1785    }
1786    if (returnValue < posEpsilon)
1787      returnValue = posEpsilon;
1788    return(returnValue);
1789 }
1790 
1791 
1792 static double columnSpecificPseudocounts(posSearchItems *posSearch, 
1793                                   compactSearchItems *compactSearch, 
1794                                   Int4 columnNumber, 
1795                                   double *backgroundProbabilities,
1796                                   double observations)
1797 {
1798   double columnProbabilitiesInitial[EFFECTIVE_ALPHABET];
1799   double columnProbabilitiesAdjusted[EFFECTIVE_ALPHABET];
1800   double relativeEntropy; /*relative entropy of this column to background probs.*/
1801   double alpha; /*intermediate term*/
1802   double pseudoDenominator; /*intermediate term*/
1803   double returnValue;
1804 
1805   fillColumnProbabilities(&(columnProbabilitiesInitial[0]), posSearch, columnNumber);
1806   adjustColumnProbabilities(&(columnProbabilitiesInitial[0]), 
1807                             &(columnProbabilitiesAdjusted[0]),
1808                               compactSearch->standardProbWeight,
1809                               backgroundProbabilities, observations);
1810   relativeEntropy = computeRelativeEntropy(&(columnProbabilitiesAdjusted[0]),
1811                                            backgroundProbabilities);
1812   pseudoDenominator = pow(relativeEntropy, compactSearch->HmethodDenominator);
1813   alpha = compactSearch->HmethodNumerator/pseudoDenominator;
1814   if (alpha < (1.0 - posEpsilon))
1815     returnValue = PSEUDO_MULTIPLIER * alpha/ (1- alpha);
1816   else
1817     returnValue = PSEUDO_MAX;
1818   /*extraOutputFile = fopen("Pseudocounts.txt","a");
1819   fprintf(extraOutputFile,"%s\t%5d\t%3.6lf\t%3.6lf\t%3.6lf\t%3.6lf",compactSearch->queryFileName,columnNumber+1,observations+1,relativeEntropy,alpha,returnValue);
1820   fprintf(extraOutputFile,"\n");
1821   fclose(extraOutputFile);*/
1822 
1823   return(returnValue);
1824 }
1825 
1826 
1827 Nlm_FloatHi ** LIBCALL posComputePseudoFreqs(posSearchItems *posSearch, compactSearchItems * compactSearch, Boolean Cpos)
1828 {
1829    Uint1Ptr q;  /*pointer to the query*/
1830    Int4 length;  /*length of the query*/
1831    Int4 c; /*loop index*/
1832    Int4 a, aSub, alphabetSize; /*loop indices and size of alphabet*/
1833    Nlm_FloatHi lambda; /*Karlin-Altschul parameter*/
1834    Nlm_FloatHi pseudo, numerator, denominator, qOverPEstimate; /*intermediate terms*/
1835    Nlm_FloatHi infoSum; /*sum used for information content*/
1836    Nlm_FloatHi **posFreqs; /*store frequencies*/
1837    double observations; /*estimated number of independent observations*/
1838    double  expno[MAX_IND_OBSERVATIONS+1]; /*table of expectations*/
1839    double pseudoWeight; /*multiplier for pseudocounts term*/
1840    double *backgroundProbabilities; /*background probabilities for matrix*/
1841    double columnCounts; /*column-specific pseudocounts*/
1842 
1843    q = compactSearch->query;
1844    length = compactSearch->qlength;
1845 
1846    alphabetSize = compactSearch->alphabetSize;
1847    lambda = compactSearch->lambda_ideal;
1848    posFreqs = allocatePosFreqs(length, alphabetSize);
1849    backgroundProbabilities = (double *) Blast_GetMatrixBackgroundFreq(compactSearch->standardMatrixName);
1850    if (!posSearch->stdFreqRatios) {
1851      posSearch->stdFreqRatios =
1852            PSIMatrixFrequencyRatiosNew(compactSearch->standardMatrixName);
1853    }
1854 
1855    initializeExpNumObservations(&(expno[0]),  backgroundProbabilities);
1856    compactSearch->standardProbWeight = PSEUDO_SMALL_INITIAL;
1857    compactSearch->HmethodDenominator = PSEUDO_EXPONENT;
1858    compactSearch->HmethodNumerator = PSEUDO_NUMERATOR;
1859 
1860    for(c = 0; c < length; c++) {
1861      if (Xchar != q[c]) {
1862        infoSum = 0;
1863        observations = effectiveObservations(posSearch,c,
1864                                             compactSearch->qlength,
1865                                             &(expno[0]));
1866        /* observations = countsFunction(posSearch->posSigma[c], 
1867           posSearch->posIntervalSizes[c]);*/
1868        if (0 == compactSearch->pseudoCountConst)
1869          columnCounts = columnSpecificPseudocounts(posSearch,compactSearch, c, backgroundProbabilities, observations);
1870         else
1871          columnCounts = compactSearch->pseudoCountConst;
1872        if (columnCounts >= PSEUDO_MAX) {
1873          pseudoWeight = ZERO_OBS_PSEUDO;
1874          observations = 0;
1875        }
1876        else {
1877          pseudoWeight = columnCounts;
1878        }
1879        for(a = 0; a < alphabetSize; a++) {
1880          if (compactSearch->standardProb[a] > posEpsilon) {
1881            pseudo = 0;
1882            /*changed to matrix specific ratios here May 2000*/
1883            for (aSub = 0; aSub < alphabetSize; aSub++)
1884              if(compactSearch->matrix[a][aSub] != BLAST_SCORE_MIN) 
1885                pseudo += (posSearch->posMatchWeights[c][aSub] *
1886                         posSearch->stdFreqRatios->data[a][aSub]);
1887            pseudo *= pseudoWeight;
1888            numerator = pseudo + 
1889              (observations * posSearch->posMatchWeights[c][a]/
1890                 compactSearch->standardProb[a]);
1891            denominator = observations + pseudoWeight;
1892            qOverPEstimate = numerator / denominator;
1893            /*Note artificial multiplication by standard probability to
1894              normalize*/
1895            posFreqs[c][a] = qOverPEstimate * compactSearch->standardProb[a];
1896          if (0.0 != qOverPEstimate && (compactSearch->standardProb[a] > posEpsilon))
1897            infoSum += qOverPEstimate * compactSearch->standardProb[a] * log(qOverPEstimate)/ NCBIMATH_LN2;
1898           }
1899         else
1900           posFreqs[c][a] = 0.0;
1901        }
1902        if (Cpos)
1903          posSearch->posInformation[c] = infoSum;
1904      }
1905      else
1906        for(a = 0; a < alphabetSize; a++) {
1907          posFreqs[c][a] = 0;
1908        }
1909    }
1910   return(posFreqs);
1911 }
1912 
1913 void LIBCALL posScaling(posSearchItems *posSearch, compactSearchItems * compactSearch)
1914 {
1915         BlastMatrixRescalePtr matrix_rescale;
1916 
1917         matrix_rescale = BlastMatrixRescaleNew(compactSearch->alphabetSize, 
1918                                                 compactSearch->qlength,
1919                                                 compactSearch->query,
1920                                                 compactSearch->standardProb,
1921                                                 posSearch->posMatrix,
1922                                                 posSearch->posPrivateMatrix,
1923                                                 compactSearch->kbp_std,
1924                                                 compactSearch->kbp_psi,
1925                                                 compactSearch->kbp_gap_std,
1926                                                 compactSearch->kbp_gap_psi,
1927                                                 compactSearch->lambda_ideal,
1928                                                 compactSearch->K_ideal);
1929 
1930         BlastScaleMatrix(matrix_rescale, TRUE);
1931 
1932         matrix_rescale = BlastMatrixRescaleDestruct(matrix_rescale);
1933 
1934         return;
1935 }
1936 
1937 
1938 Int4Ptr * LIBCALL CposComputation(posSearchItems *posSearch, BlastSearchBlkPtr search, compactSearchItems * compactSearch, SeqAlignPtr listOfSeqAligns, Char *ckptFileName, Boolean patternSearchStart, Int4 scorematOutput, Bioseq *query_bsp, Int4 gap_open, Int4 gap_extend, ValNodePtr * error_return, Nlm_FloatHi weightExponent)
1939 {
1940     Int4 numalign, numseq; /*number of alignments and matches in previous round*/
1941     
1942     search->posConverged = FALSE;
1943     /*  if (patternSearchStart)
1944         posAllocateMemory(posSearch, compactSearch->alphabetSize, compactSearch->qlength, posSearch->posNumSequences);
1945         else {
1946     */
1947     numalign = countSeqAligns(listOfSeqAligns, &numseq, FALSE, 0.0);
1948     countNumSeq(posSearch, compactSearch, listOfSeqAligns, &numseq);
1949     posAllocateMemory(posSearch, compactSearch->alphabetSize, compactSearch->qlength, numseq);
1950     
1951     if (!patternSearchStart)
1952         findThreshSequences(posSearch, search, listOfSeqAligns, numalign, numseq);
1953     posDemographics(posSearch, compactSearch, listOfSeqAligns);
1954     posPurgeMatches(posSearch, compactSearch, error_return);
1955     posComputeExtents(posSearch, compactSearch);
1956     posComputeSequenceWeights(posSearch, compactSearch, weightExponent);
1957     posCheckWeights(posSearch, compactSearch);
1958     posSearch->posFreqs = posComputePseudoFreqs(posSearch, compactSearch, TRUE);
1959     if (NULL == search->sbp->posFreqs)
1960       search->sbp->posFreqs =  allocatePosFreqs(compactSearch->qlength, compactSearch->alphabetSize);
1961     copyPosFreqs(posSearch->posFreqs,search->sbp->posFreqs, compactSearch->qlength, compactSearch->alphabetSize);
1962     if (NULL != ckptFileName) {
1963       if (scorematOutput == NO_SCOREMAT_IO)
1964         posTakeCheckpoint(posSearch, compactSearch, ckptFileName, error_return);
1965       else
1966         posTakeScoremat(posSearch, compactSearch, ckptFileName,
1967                         scorematOutput, query_bsp, gap_open,
1968                         gap_extend, error_return);
1969     }
1970     posFreqsToMatrix(posSearch,compactSearch);
1971     posScaling(posSearch, compactSearch);
1972     return posSearch->posMatrix;
1973 }
1974 
1975 /* Top-level routine to compute position-specific matrix, when used through
1976 the Web, one round at a time*/
1977 Int4Ptr * LIBCALL WposComputation(compactSearchItems * compactSearch, SeqAlignPtr listOfSeqAligns, Nlm_FloatHi ** posFreqs)
1978 {
1979     posSearchItems *posSearch;
1980     Int4 i, numSeqAligns, numseq, qlength;
1981     Int2 alphabetSize;
1982     Int4Ptr *posMatrix;
1983     
1984     /* Why isn't posAllocateMemory() called? */
1985     posSearch = (posSearchItems *) MemNew(1 * sizeof(posSearchItems));
1986     qlength = compactSearch->qlength;
1987     alphabetSize = compactSearch->alphabetSize;
1988 
1989     if (listOfSeqAligns != NULL) {
1990        numSeqAligns = countSeqAligns(listOfSeqAligns, &numseq, FALSE, 0.0);
1991        countNumSeq(posSearch, compactSearch, listOfSeqAligns, &numseq);
1992        posAllocateMemory(posSearch, alphabetSize, 
1993                          qlength, numseq);
1994        posDemographics(posSearch, compactSearch, listOfSeqAligns);
1995        posPurgeMatches(posSearch, compactSearch, NULL);
1996        posComputeExtents(posSearch, compactSearch);
1997        posComputeSequenceWeights(posSearch, compactSearch, 1.0);
1998        posCheckWeights(posSearch, compactSearch);
1999        posSearch->posFreqs = posComputePseudoFreqs(posSearch, compactSearch, 
2000                                                    FALSE);
2001        copyPosFreqs(posSearch->posFreqs,posFreqs, qlength, alphabetSize);
2002     } else {
2003        /* Assume that posFreqs are already filled, use them to calculate
2004           posMatrix.
2005           If listOfSeqAligns is NULL as a result of search, all frequencies are
2006           0 anyway, so there is no need to compute them. However if it is
2007           deliberately passed as NULL before search, this means that posFreqs
2008           are passed as input from PSSM.
2009        */
2010        posSearch->posFreqs = posFreqs;
2011        ASSERT(compactSearch->standardMatrixName);
2012        posSearch->stdFreqRatios =
2013            PSIMatrixFrequencyRatiosNew(compactSearch->standardMatrixName);
2014        posSearch->posMatrix = (BLAST_Score **) MemNew((qlength + 1) * sizeof(BLAST_Score *));
2015        posSearch->posPrivateMatrix = (BLAST_Score **) MemNew((qlength + 1) * sizeof(BLAST_Score *));
2016        for(i = 0; i <= qlength; i++) {
2017           posSearch->posMatrix[i] = (BLAST_Score *) MemNew(alphabetSize * sizeof(BLAST_Score));
2018           posSearch->posPrivateMatrix[i] = (BLAST_Score *) MemNew(alphabetSize * sizeof(BLAST_Score));
2019        }
2020     }
2021     posFreqsToMatrix(posSearch,compactSearch);
2022     posScaling(posSearch, compactSearch);
2023     posMatrix = posSearch->posMatrix;
2024     
2025     /* Why isn't posFreeMemory() called? */
2026     if (listOfSeqAligns != NULL) {
2027        for(i = 0; i <= qlength ; i++) {
2028           MemFree(posSearch->posFreqs[i]);
2029           MemFree(posSearch->posMatchWeights[i]);
2030           MemFree(posSearch->posC[i]);
2031        }
2032        
2033        MemFree(posSearch->posFreqs);
2034        MemFree(posSearch->posMatchWeights);
2035        MemFree(posSearch->posC);
2036        MemFree(posSearch->posA);
2037        MemFree(posSearch->posExtents);
2038        MemFree(posSearch->posSigma);
2039        MemFree(posSearch->posRowSigma);
2040        MemFree(posSearch->posIntervalSizes);
2041        MemFree(posSearch->posCount);
2042        
2043        for(i = 0; i <= posSearch->posDescMatrixLength; i++) {
2044           MemFree(posSearch->posDescMatrix[i]);
2045        }
2046        MemFree(posSearch->posDescMatrix);
2047     }
2048 
2049     for(i = 0; i <= qlength ; i++)
2050        MemFree(posSearch->posPrivateMatrix[i]);
2051     MemFree(posSearch->posPrivateMatrix);
2052     posSearch->stdFreqRatios = PSIMatrixFrequencyRatiosFree(posSearch->stdFreqRatios);
2053     MemFree(posSearch);
2054 
2055     return posMatrix;
2056 }
2057 
2058 
2059 static Char getRes(Char input)
2060 {
2061     switch(input) 
2062       {
2063       case 0: 
2064         return('-');
2065       case 1: 
2066         return('A');
2067       case 2: 
2068         return('B');
2069       case 3: 
2070         return('C');
2071       case 4: 
2072         return('D');
2073       case 5: 
2074         return('E');
2075       case 6: 
2076         return('F');
2077       case 7: 
2078         return('G');
2079       case 8: 
2080         return('H');
2081       case 9: 
2082         return('I');
2083       case 10: 
2084         return('K');
2085       case 11: 
2086         return('L');
2087       case 12: 
2088         return('M');
2089       case 13: 
2090         return('N');
2091       case 14: 
2092         return('P');
2093       case 15: 
2094         return('Q');
2095       case 16: 
2096         return('R');
2097       case 17: 
2098         return('S');
2099       case 18: 
2100         return('T');
2101       case 19: 
2102         return('V');
2103       case 20: 
2104         return('W');
2105       case 21: 
2106         return('X');
2107       case 22: 
2108         return('Y');
2109       case 23: 
2110         return('Z');
2111       case 24: 
2112         return('U');
2113       case 25: 
2114         return('*');
2115       case 26: 
2116         return('O');
2117       case 27: 
2118         return('J');
2119       default:
2120         return('?');
2121     }
2122 }
2123 Uint1 LIBCALL ResToInt(Char input)
2124 {
2125     switch(input) 
2126       {
2127       case '-': 
2128         return(0);
2129       case 'A': 
2130         return(1);
2131       case 'B': 
2132         return(2);
2133       case 'C': 
2134         return(3);
2135       case 'D': 
2136         return(4);
2137       case 'E': 
2138         return(5);
2139       case 'F': 
2140         return(6);
2141       case 'G': 
2142         return(7);
2143       case 'H': 
2144         return(8); 
2145       case 'I': 
2146         return(9);
2147       case 'K': 
2148         return(10);
2149       case 'L': 
2150         return(11);
2151       case 'M': 
2152         return(12);
2153       case 'N': 
2154         return(13);
2155       case 'P': 
2156         return(14);
2157       case 'Q': 
2158         return(15);
2159       case 'R': 
2160         return(16);
2161       case 'S': 
2162         return(17);
2163       case 'T': 
2164         return(18);
2165       case 'V': 
2166         return(19);
2167       case 'W': 
2168         return(20);
2169       case 'X': 
2170         return(21);
2171       case 'Y': 
2172         return(22);
2173       case 'Z': 
2174         return(23);
2175       case 'U': 
2176         return(24);
2177       case '*': 
2178         return(25);
2179       case 'O': 
2180         return(26);
2181       case 'J': 
2182         return(27);
2183       default:
2184         return(-1);
2185     }
2186 }
2187 
2188 
2189 /*Print out the position-specific matrix*/
2190 void LIBCALL outputPosMatrix(posSearchItems *posSearch, compactSearchItems *compactSearch, FILE *matrixfp, Boolean posComputationCalled)
2191 {
2192    Uint1Ptr q; /*query sequence*/
2193    Int4 i; /*loop indices*/
2194    Int4 c; /*index over alphabet*/
2195    Int4 length; /*length of query*/
2196    Int4 charOrder[EFFECTIVE_ALPHABET]; /*standard order of letters according to S. Altschul*/
2197 
2198    if (compactSearch->alphabetSize != PROTEIN_ALPHABET){
2199      ErrPostEx(SEV_ERROR, 0, 0, "\nCannot print diagnostic information because alphabet size is not %ld", (long) compactSearch->alphabetSize);
2200      return;
2201    }
2202    
2203    charOrder[0] =  1;  /*A*/
2204    charOrder[1] =  16; /*R*/
2205    charOrder[2] =  13; /*N*/  
2206    charOrder[3] =  4;  /*D*/ 
2207    charOrder[4] =  3;  /*C*/
2208    charOrder[5] =  15; /*Q*/
2209    charOrder[6] =  5;  /*E*/ 
2210    charOrder[7] =  7;  /*G*/
2211    charOrder[8] =  8;  /*H*/
2212    charOrder[9] =  9;  /*I*/
2213    charOrder[10] = 11; /*L*/
2214    charOrder[11] = 10; /*K*/
2215    charOrder[12] = 12; /*M*/  
2216    charOrder[13] =  6; /*F*/
2217    charOrder[14] = 14; /*P*/
2218    charOrder[15] = 17; /*S*/
2219    charOrder[16] = 18; /*T*/
2220    charOrder[17] = 20; /*W*/
2221    charOrder[18] = 22; /*Y*/
2222    charOrder[19] = 19; /*V*/
2223 
2224    q = compactSearch->query;
2225    length = compactSearch->qlength;
2226    
2227 /* Used ifdef until final decision is made on output. */
2228 
2229 #ifdef POSIT_DEBUG
2230    printf("\nCharacter Frequencies by positon\n");
2231    printf("         ");
2232    for (c = 0; c< EFFECTIVE_ALPHABET; c++)
2233       printf("  %c",getRes((Char) charOrder[c]));
2234    for(i=0; i < length; i++) {
2235      printf("\n%5d %c   ", i + 1, getRes(q[i]));
2236      for (c = 0; c < EFFECTIVE_ALPHABET; c++) 
2237        printf("%2d ", posSearch->posC[i][charOrder[c]]);
2238    }
2239    printf("\n\n");
2240    printf("\nposition counts used. multiplied by 10 and rounded and");
2241    printf("\nposition character weights used, multiplied by 10 and rounded\n");
2242    printf("        Counts");
2243    for (c = 0; c< EFFECTIVE_ALPHABET; c++)
2244       printf("  %c",getRes((Char) charOrder[c]));
2245    printf(" Extent ");
2246    for(i=0; i < length; i++) {
2247      printf("\n%5d %c   ", i + 1, getRes(q[i]));
2248      if ((posSearch->posCount[i] > 1) && (Xchar != q[i]))
2249        printf("%4d ", (Int4) posit_rounddown(10 * countsFunction
2250                                      (posSearch->posSigma[i],posSearch->posIntervalSizes[i])));
2251      else
2252        printf("     ");
2253      for (c = 0; c< EFFECTIVE_ALPHABET; c++)
2254        if((posSearch->posMatrix[i][charOrder[c]] == BLAST_SCORE_MIN) ||
2255              (0.0 == posSearch->posMatchWeights[i][charOrder[c]]))
2256            printf(" - ");
2257          else
2258            printf("%2d ", (Int4) posit_rounddown(10 * posSearch->posMatchWeights[i][charOrder[c]]));
2259      printf(" %4d",posSearch->posExtents[i].rightExtent - posSearch->posExtents[i].leftExtent +1);
2260    }
2261    printf("\n\n");
2262 #endif
2263    if (NULL != matrixfp) {
2264      if (posComputationCalled) {
2265        fprintf(matrixfp,"\nLast position-specific scoring matrix computed, weighted observed percentages rounded down, information per position, and relative weight of gapless real matches to pseudocounts\n");
2266      }
2267      else {
2268        fprintf(matrixfp,"\nLast position-specific scoring matrix computed\n");
2269      }
2270      fprintf(matrixfp,"         ");
2271      for (c = 0; c< EFFECTIVE_ALPHABET; c++)
2272        fprintf(matrixfp,"  %c",getRes((Char) charOrder[c]));
2273      if (posComputationCalled) {
2274        for (c = 0; c< EFFECTIVE_ALPHABET; c++)
2275          fprintf(matrixfp,"   %c",getRes((Char) charOrder[c]));
2276      }
2277      for(i=0; i < length; i++) {
2278        fprintf(matrixfp,"\n%5ld %c   ", (long) (i + 1), getRes(q[i]));
2279        /*fprintf(matrixfp,"\n          ");*/
2280        for (c = 0; c < EFFECTIVE_ALPHABET; c++) 
2281          if(posSearch->posMatrix[i][charOrder[c]] == BLAST_SCORE_MIN)
2282            fprintf(matrixfp,"-I ");
2283          else
2284            fprintf(matrixfp,"%2ld ", (long) posSearch->posMatrix[i][charOrder[c]]);
2285        if (posComputationCalled) {
2286          for (c = 0; c < EFFECTIVE_ALPHABET; c++) 
2287            if(posSearch->posMatrix[i][charOrder[c]] != BLAST_SCORE_MIN)
2288              fprintf(matrixfp, "%4d", (Int4) posit_rounddown(100 * posSearch->posMatchWeights[i][charOrder[c]]));
2289          fprintf(matrixfp," %5.2f", posSearch->posInformation[i]); 
2290          if ((posSearch->posCount[i] > 1) && (Xchar != q[i]))
2291            fprintf(matrixfp," %.2f", countsFunction(posSearch->posSigma[i],
2292                      posSearch->posIntervalSizes[i]) * 
2293                  posSearch->posGaplessColumnWeights[i]/
2294                  compactSearch->pseudoCountConst);
2295          else
2296            fprintf(matrixfp,"    0.00");
2297        }
2298      }
2299      fprintf(matrixfp,"\n\n");
2300      fprintf(matrixfp,"                      K         Lambda\n");
2301      fprintf(matrixfp,"Standard Ungapped    %6.4f     %6.4f\n",compactSearch->kbp_std[0]->K,compactSearch->kbp_std[0]->Lambda);
2302      fprintf(matrixfp,"Standard Gapped      %6.4f     %6.4f\n",compactSearch->kbp_gap_std[0]->K,compactSearch->kbp_gap_std[0]->Lambda);
2303      fprintf(matrixfp,"PSI Ungapped         %6.4f     %6.4f\n",compactSearch->kbp_psi[0]->K,compactSearch->kbp_psi[0]->Lambda);
2304      fprintf(matrixfp,"PSI Gapped           %6.4f     %6.4f\n",compactSearch->kbp_gap_psi[0]->K,compactSearch->kbp_gap_psi[0]->Lambda);
2305    }
2306 }
2307 
2308 
2309 void LIBCALL posPrintInformation(posSearchItems *posSearch, BlastSearchBlkPtr search, Int4 passNum)
2310 {
2311   Int4 querySize;
2312 
2313   querySize = search->context[0].query->length;
2314 
2315 /* Used ifdef until final decision is made on output. */
2316 #ifdef POSIT_DEBUG
2317   {{
2318       Int4 c;
2319   
2320       printf("\nInformation content by position for pass %d\n", passNum);
2321       for(c = 0; c < querySize; c++)
2322           printf(" %5d", c); 
2323       printf("\n");
2324       for(c = 0; c < querySize; c++)
2325           printf(" %5.2lf", posSearch->posInformation[c]); 
2326       printf("\n");
2327   }}
2328 #endif
2329 }   
2330  
2331 void LIBCALL posInitializeInformation(posSearchItems *posSearch, BlastSearchBlkPtr search)
2332 {
2333   Uint1Ptr query;
2334   Int4 querySize;
2335   Int4 c, a, alphabetSize;
2336   BLAST_ScoreBlkPtr sbp;
2337   BLAST_ResFreqPtr stdrfp; /*standard frequencies*/
2338   Nlm_FloatHi lambda;
2339   Nlm_FloatHi term1, term2, term3, term4;
2340   Nlm_FloatHi infoSum;
2341  
2342   querySize = search->context[0].query->length;
2343   query = search->context[0].query->sequence;
2344   posSearch->posInformation = (Nlm_FloatHi *) MemNew(querySize * sizeof(Nlm_FloatHi));
2345   if (NULL == posSearch->posInformation)
2346     exit(EXIT_FAILURE);
2347   for(c = 0; c < querySize; c++)
2348     posSearch->posInformation[c] = 0.0;
2349   alphabetSize = search->sbp->alphabet_size;
2350   /*Compute standard frequencies as in BlastScoreBlkFill in blastkar.c*/
2351   sbp = search->sbp;
2352   stdrfp = BlastResFreqNew(sbp);
2353   BlastResFreqStdComp(sbp,stdrfp); 
2354   lambda = search->sbp->kbp[0]->Lambda;
2355   for(c = 0; c < querySize; c++) {
2356     infoSum = 0;
2357     for(a = 0; a < alphabetSize; a++)
2358       if (stdrfp->prob[a] > posEpsilon) {
2359         term1 = search->sbp->matrix[query[c]][a];
2360         term2 = term1 * lambda;
2361         term3 = exp(term2);
2362         term4 = stdrfp->prob[a] * term3;
2363         infoSum += term4 * log(term4/stdrfp->prob[a])/NCBIMATH_LN2;
2364       }
2365     posSearch->posInformation[c] = infoSum;
2366   }
2367   BlastResFreqFree(stdrfp);
2368 }
2369 
2370 /*
2371         Is this function used?
2372 */
2373 
2374 void LIBCALL posFreeInformation(posSearchItems *posSearch)
2375 {
2376   MemFree(posSearch->posInformation);
2377 }
2378 
2379 /*Copy a few fields from the lasrge record search into the small record
2380   compactSearch, so that a small amount of information
2381   is passed into posit.c*/
2382 void LIBCALL copySearchItems(compactSearchItems * compactSearch, BlastSearchBlkPtr search, char * matrixName)
2383 {
2384    BLAST_ResFreqPtr stdrfp; /* gets standard frequencies in prob field */
2385    Int4 a; /*index over characters*/
2386 
2387    compactSearch->query = search->context[0].query->sequence;
2388    compactSearch->qlength = search->context[0].query->length;
2389    compactSearch->gapped_calculation = search->pbp->gapped_calculation;
2390    compactSearch->alphabetSize = search->sbp->alphabet_size;
2391    compactSearch->pseudoCountConst = search->pbp->pseudoCountConst;
2392    compactSearch->ethresh = search->pbp->ethresh;
2393    compactSearch->lambda =  search->sbp->kbp[0]->Lambda;
2394    compactSearch->matrix = search->sbp->matrix;
2395    compactSearch->kbp_psi = search->sbp->kbp_psi;
2396    compactSearch->kbp_gap_psi = search->sbp->kbp_gap_psi;
2397    compactSearch->kbp_std = search->sbp->kbp_std;
2398    compactSearch->kbp_gap_std = search->sbp->kbp_gap_std;
2399    if (search->pbp->gapped_calculation) {
2400      compactSearch->lambda_ideal = search->sbp->kbp_ideal->Lambda;
2401      compactSearch->K_ideal = search->sbp->kbp_ideal->K;
2402    }
2403    else {
2404      compactSearch->lambda_ideal = search->sbp->kbp[0] ->Lambda;
2405      compactSearch->K_ideal = search->sbp->kbp[0]->K;
2406    }
2407    compactSearch->use_best_align = search->pbp->use_best_align;
2408 
2409    stdrfp = BlastResFreqNew(search->sbp);
2410    BlastResFreqStdComp(search->sbp,stdrfp); 
2411    compactSearch->standardProb = MemNew(compactSearch->alphabetSize * sizeof(Nlm_FloatHi));
2412    if (NULL == compactSearch->standardProb)
2413      exit(EXIT_FAILURE);
2414    for(a = 0; a < compactSearch->alphabetSize; a++)
2415      compactSearch->standardProb[a] = stdrfp->prob[a];
2416    stdrfp = BlastResFreqDestruct(stdrfp);
2417    strcpy(compactSearch->standardMatrixName,matrixName);
2418 }
2419 
2420 /*allocate memory for a record of type compactSearchItems*/
2421 compactSearchItems * LIBCALL  compactSearchNew(compactSearchItems * compactSearch)
2422 {
2423    compactSearch = MemNew(1 * sizeof(compactSearchItems));
2424    if (NULL == compactSearch)
2425      exit(EXIT_FAILURE);
2426    return(compactSearch);
2427 }
2428 
2429 /*De-allocate memory for a record of type compactSearchItems*/
2430 void LIBCALL compactSearchDestruct(compactSearchItems * compactSearch)
2431 {
2432 
2433    MemFree(compactSearch->standardProb);
2434    MemFree(compactSearch);
2435 }
2436 
2437 /*Some of the following checkpointing code is taken and adapted from
2438 code written by K. Shriram for FASTLINK.
2439 Reference:
2440  A. A. Schaffer, S. K. Gupta, K. Shriram, and R. W. Cottingham, Jr. 
2441  Avoiding Recomputation in Linkage Analysis,
2442  Human Heredity 44(1994), pp. 225-237. */
2443 
2444 
2445 #define  putCkptNlm_FloatHi(d, ckptFile)  (putCkptNumber(&(d),sizeof(Nlm_FloatHi),ckptFile))
2446 #define  putCkptInt4(i, ckptFile)         (putCkptNumber(&(i),sizeof(Int4),ckptFile))
2447 #define  putCkptChar(c, ckptFile)         (putCkptNumber(&(c),sizeof(Char),ckptFile))
2448  
2449 /* General routine for putting the internal representation of a number. */
2450  
2451 static void  putCkptNumber(void * numberPtr, Int4 numberSize, FILE * ckptFile )
2452 {
2453   FileWrite(numberPtr,numberSize,1,ckptFile) ;
2454 }
2455 
2456 /*Code to put a vector of frequencies; put only the interesting
2457   entries*/
2458 static void  putFreqVector(Nlm_FloatHi * theVector, Int4 length, FILE * ckptFile)
2459 {
2460    int  vectorRef;
2461    Int4 charOrder[EFFECTIVE_ALPHABET]; /*standard order of letters according to S. Altschul*/
2462 
2463 
2464    charOrder[0] =  1;  /*A*/
2465    charOrder[1] =  16; /*R*/
2466    charOrder[2] =  13; /*N*/  
2467    charOrder[3] =  4;  /*D*/ 
2468    charOrder[4] =  3;  /*C*/
2469    charOrder[5] =  15; /*Q*/
2470    charOrder[6] =  5; /*E*/ 
2471    charOrder[7] =  7;  /*G*/
2472    charOrder[8] =  8;  /*H*/
2473    charOrder[9] =  9;  /*I*/
2474    charOrder[10] = 11; /*L*/
2475    charOrder[11] = 10; /*K*/
2476    charOrder[12] = 12; /*M*/  
2477    charOrder[13] =  6; /*F*/
2478    charOrder[14] = 14; /*P*/
2479    charOrder[15] = 17; /*S*/
2480    charOrder[16] = 18; /*T*/
2481    charOrder[17] = 20; /*W*/
2482    charOrder[18] = 22; /*Y*/
2483    charOrder[19] = 19; /*V*/
2484 
2485  
2486    for(vectorRef = 0; vectorRef < EFFECTIVE_ALPHABET; vectorRef++)
2487      putCkptNlm_FloatHi(theVector[charOrder[vectorRef]],ckptFile);
2488 }
2489 
2490  
2491 /* Code to put a matrix, vector-by-vector. */
2492 static void    putCkptFreqMatrix (Nlm_FloatHi **theMatrix, Int4 length, Int4 width, FILE * ckptFile)
2493 {
2494   int  matrixRef;  /*loop index*/
2495  
2496   for (matrixRef = 0; matrixRef < length ; matrixRef++ )
2497     putFreqVector(theMatrix[matrixRef], width, ckptFile);
2498 }
2499 
2500  
2501 /* General routine for getting the internal representation of a number. */
2502  
2503 void  LIBCALL getCkptNumber(void * numberPtr, Int4 numberSize, FILE * ckptFile )
2504 {
2505   FileRead(numberPtr,numberSize,1,ckptFile) ;
2506 }
2507 
2508 static void    getFreqVector (Nlm_FloatHi * theVector, Int4 length, FILE * ckptFile)
2509 {
2510    int  vectorRef ;
2511 
2512    Int4 charOrder[EFFECTIVE_ALPHABET]; /*standard order of letters according to S. Altschul*/
2513 
2514 
2515    charOrder[0] =  1;  /*A*/
2516    charOrder[1] =  16; /*R*/
2517    charOrder[2] =  13; /*N*/  
2518    charOrder[3] =  4;  /*D*/ 
2519    charOrder[4] =  3;  /*C*/
2520    charOrder[5] =  15; /*Q*/
2521    charOrder[6] =  5; /*E*/ 
2522    charOrder[7] =  7;  /*G*/
2523    charOrder[8] =  8;  /*H*/
2524    charOrder[9] =  9;  /*I*/
2525    charOrder[10] = 11; /*L*/
2526    charOrder[11] = 10; /*K*/
2527    charOrder[12] = 12; /*M*/  
2528    charOrder[13] =  6; /*F*/
2529    charOrder[14] = 14; /*P*/
2530    charOrder[15] = 17; /*S*/
2531    charOrder[16] = 18; /*T*/
2532    charOrder[17] = 20; /*W*/
2533    charOrder[18] = 22; /*Y*/
2534    charOrder[19] = 19; /*V*/
2535  
2536   for(vectorRef = 0; vectorRef < length; vectorRef++)
2537     theVector[vectorRef] = 0;
2538   for(vectorRef = 0; vectorRef < EFFECTIVE_ALPHABET; vectorRef++)
2539     getCkptNlm_FloatHi(theVector[charOrder[vectorRef]],ckptFile) ;
2540 }
2541 
2542 /* Code to frequency matrix, vector-by-vector. */
2543  
2544 void    LIBCALL getCkptFreqMatrix (Nlm_FloatHi ** theMatrix, Int4 length, Int4 width, FILE * ckptFile)
2545 {
2546   Int4  matrixRef;  /*loop index*/
2547  
2548   for (matrixRef = 0; matrixRef < length ; matrixRef++ )
2549     getFreqVector(theMatrix[matrixRef], width, ckptFile);
2550 }
2551 
2552 /*Take a checkpoint at the end of the current PSI-BLAST round, stores
2553 query length, query, and position-specific target frequencies.
2554 Returns TRUE if checkpoint was sucessful and FALSE otherwise. */
2555 Boolean LIBCALL posTakeCheckpoint(posSearchItems * posSearch, compactSearchItems * compactSearch, CharPtr fileName, ValNodePtr *error_return)
2556 {
2557   FILE * checkFile; /*file in which to take the checkpoint*/
2558   Int4 length; /*length of query sequence, and an index for it*/
2559   Int4 i; /*indices to position and alphabet */
2560   Char localChar; /*temporary character*/
2561 
2562   checkFile = FileOpen(fileName, "wb");
2563   if (NULL == checkFile) {
2564     BlastConstructErrorMessage("posTakeCheckpoint", "Could not open checkpoint file", 1, error_return);
2565     return(FALSE);
2566   }
2567   length = compactSearch->qlength;
2568   putCkptInt4(length, checkFile);
2569   for(i = 0; i < length; i++) {
2570     localChar = getRes(compactSearch->query[i]);
2571     putCkptChar(localChar, checkFile);
2572   }  
2573   putCkptFreqMatrix(posSearch->posFreqs,length,compactSearch->alphabetSize, checkFile);
2574   FileClose(checkFile);
2575   return(TRUE);
2576 }
2577 
2578 /* Like posTakeCheckpoint, posTakeScoremat will emit the position
2579    frequencies that have been generated. Unlike that routine, the
2580    file to be written is an ASN.1 encoded PssmWithParameters object. */
2581 
2582 Boolean LIBCALL posTakeScoremat(posSearchItems *posSearch, 
2583                        compactSearchItems *compactSearch, 
2584                        CharPtr filename, Int4 scorematOutput,
2585                        Bioseq *query_bsp, Int4 gap_open, 
2586                        Int4 gap_extend, ValNodePtr *error_return)
2587 {
2588   AsnIoPtr outfile = NULL;
2589   PssmWithParametersPtr scoremat = NULL;
2590   PssmIntermediateDataPtr freqs = NULL;
2591   PssmParametersPtr params = NULL;
2592   FormatRpsDbParametersPtr rpsparams = NULL;
2593   PssmPtr pssm = NULL;
2594   Int4 i, j;
2595   Boolean status = FALSE;
2596 
2597   scoremat = PssmWithParametersNew();
2598   if (scoremat == NULL) {
2599     BlastConstructErrorMessage("posTakeScoremat", 
2600                "Could not allocate PssmWithParameters", 1, error_return);
2601     goto bail_out;
2602   }
2603 
2604   /* Add information about the underlying score matrix.
2605      Note that blastpgp will ignore this information */
2606 
2607   params = scoremat->params = PssmParametersNew();
2608   if (params == NULL) {
2609     BlastConstructErrorMessage("posTakeScoremat", 
2610                "Could not allocate PssmParameters", 1, error_return);
2611     goto bail_out;
2612   }
2613   rpsparams = params->rpsdbparams = FormatRpsDbParametersNew();
2614   if (params == NULL) {
2615     BlastConstructErrorMessage("posTakeScoremat", 
2616                "Could not allocate RpsDbParameters", 1, error_return);
2617     goto bail_out;
2618   }
2619   rpsparams->matrixName = strdup(compactSearch->standardMatrixName);
2620   rpsparams->gapOpen = gap_open;
2621   rpsparams->gapExtend = gap_extend;
2622 
2623   /* Build up the objects describing the frequency ratios */
2624 
2625   pssm = scoremat->pssm = PssmNew();
2626   if (pssm == NULL) {
2627     BlastConstructErrorMessage("posTakeScoremat", 
2628                "Could not allocate PSSM object", 1, error_return);
2629     goto bail_out;
2630   }
2631   freqs = pssm->intermediateData = PssmIntermediateDataNew();
2632   if (freqs == NULL) {
2633     BlastConstructErrorMessage("posTakeScoremat", 
2634                "Could not allocate PssmIntermediateData", 1, error_return);
2635     goto bail_out;
2636   }
2637 
2638   pssm->isProtein = TRUE;
2639   pssm->numRows = compactSearch->alphabetSize;
2640   pssm->numColumns = compactSearch->qlength;
2641 
2642   for (i = 0; i < pssm->numColumns; i++) {
2643     for (j = 0; j < pssm->numRows; j++) {
2644       ValNodeAddFloat(&freqs->freqRatios, 0, posSearch->posFreqs[i][j]);
2645     }
2646   }
2647 
2648   /* Do not make a copy of the query bioseq; use it directly.
2649      The '1' below indicates a single bioseq (not a bioseq-set) */
2650 
2651   ValNodeAddPointer(&pssm->query, 1, query_bsp);
2652   if (pssm->query == NULL) {
2653     BlastConstructErrorMessage("posTakeScoremat", 
2654                "Could not attach bioseq to scoremat", 1, error_return);
2655     goto bail_out;
2656   }
2657 
2658   if (scorematOutput == ASCII_SCOREMAT)
2659      outfile = AsnIoOpen(filename, "w");
2660   else
2661      outfile = AsnIoOpen(filename, "wb");
2662 
2663   if (outfile == NULL) {
2664     ErrPostEx(SEV_FATAL, 1, 0, "Unable to open matrix output file %s\n", 
2665           filename);
2666     goto bail_out;
2667   }
2668 
2669   PssmWithParametersAsnWrite(scoremat, outfile, NULL);
2670   status = TRUE;
2671 
2672 bail_out:
2673   AsnIoClose(outfile);
2674 
2675   /* explicitly free the ValNode pointing to the query bioseq.
2676      This will prevent the ScoreMatrix freeing routine
2677      from also freeing the query bioseq, which we did not
2678      allocate */
2679 
2680   pssm->query = ValNodeFree(pssm->query);
2681 
2682   /* free everything else */
2683 
2684   scoremat = PssmWithParametersFree(scoremat);
2685   return status;
2686 }
2687 
2688 static Boolean LIBCALL posReadPosFreqsScoremat(posSearchItems * posSearch, compactSearchItems * compactSearch, CharPtr fileName, Int4 scorematInput, ValNodePtr * error_return)
2689 {
2690   AsnIoPtr infile = NULL;
2691   PssmWithParametersPtr scoremat = NULL;
2692   PssmPtr pssm = NULL;
2693   PssmIntermediateDataPtr freqs = NULL;
2694   Int4 i, j, c;
2695   ValNodePtr freq_list;
2696   Bioseq *bsp;
2697 
2698   if (scorematInput == ASCII_SCOREMAT)
2699      infile = AsnIoOpen(fileName, "r");
2700   else
2701      infile = AsnIoOpen(fileName, "rb");
2702 
2703   if (infile == NULL) {
2704     ErrPostEx(SEV_WARNING, 0, 0,"Could not open scoremat file\n");
2705     return FALSE;
2706   }
2707 
2708   scoremat = PssmWithParametersAsnRead(infile, NULL);
2709   AsnIoClose(infile);
2710   if (scoremat == NULL) {
2711     ErrPostEx(SEV_WARNING, 0, 0, "Could not read scoremat from input file\n");
2712     return FALSE;
2713   }
2714   pssm = scoremat->pssm;
2715   if (pssm == NULL) {
2716     ErrPostEx(SEV_WARNING, 0, 0,"Scoremat is empty\n");
2717     PssmWithParametersFree(scoremat);
2718     return FALSE;
2719   }
2720   freqs = pssm->intermediateData;
2721   if (freqs == NULL) {
2722     ErrPostEx(SEV_WARNING, 0, 0,"Scoremat doesn't contain intermediate data\n");
2723     PssmWithParametersFree(scoremat);
2724     return FALSE;
2725   }
2726   if (freqs->freqRatios == NULL) {
2727     ErrPostEx(SEV_WARNING, 0, 0,
2728             "Scoremat does not contain frequency ratios\n");
2729     PssmWithParametersFree(scoremat);
2730     return FALSE;
2731   }
2732   if (pssm->numRows != compactSearch->alphabetSize) {
2733     ErrPostEx(SEV_WARNING, 0, 0, "Wrong alphabet size of %d in "
2734               "input scoremat\n", pssm->numRows);
2735     PssmWithParametersFree(scoremat);
2736     return FALSE;
2737   }
2738   if (!pssm->query || !pssm->query->data.ptrvalue) {
2739     ErrPostEx(SEV_WARNING, 0, 0, "Missing sequence data in input scoremat\n");
2740     PssmWithParametersFree(scoremat);
2741     return FALSE;
2742   }
2743   bsp = (Bioseq *)(pssm->query->data.ptrvalue);
2744   if (pssm->numColumns != bsp->length) {
2745     ErrPostEx(SEV_WARNING, 0, 0, "Different sequence lengths "
2746               "(%d and %d) in input scoremat\n", pssm->numColumns, bsp->length);
2747     PssmWithParametersFree(scoremat);
2748     return FALSE;
2749   }
2750   if (pssm->numColumns != compactSearch->qlength) {
2751     ErrPostEx(SEV_WARNING, 0, 0, "Scoremat sequence length "
2752               "(%d) does not match query length (%d)\n", 
2753               pssm->numColumns, compactSearch->qlength);
2754     PssmWithParametersFree(scoremat);
2755     return FALSE;
2756   }
2757   if (!bsp->seq_data || !ISA_aa(bsp->mol)) {
2758     ErrPostEx(SEV_WARNING, 0, 0, 
2759           "Sequence within checkpoint file has no data or is not protein\n");
2760     PssmWithParametersFree(scoremat);
2761     return FALSE;
2762   }
2763   if (bsp->seq_data_type == Seq_code_gap) {
2764     ErrPostEx(SEV_WARNING, 0, 0, 
2765           "Seq_code_gap passed to posReadPosFreqsScoremat\n");
2766     PssmWithParametersFree(scoremat);
2767     return FALSE;
2768   }
2769   BSSeek((ByteStorePtr) bsp->seq_data, 0, SEEK_SET);
2770 
2771   /* Convert sequence data into Seq_code_ncbistdaa */
2772   if (bsp->seq_data_type != Seq_code_ncbistdaa) {
2773 
2774       ByteStore* new_byte_store = BSConvertSeq((ByteStorePtr) bsp->seq_data,
2775                                                Seq_code_ncbistdaa,
2776                                                bsp->seq_data_type,
2777                                                bsp->length);
2778 
2779       if ( !new_byte_store ) {
2780           ErrPostEx(SEV_FATAL, 1, 0, "Failed to convert Bioseq in ASN.1 PSSM "
2781                     "to Seq_code_ncbistdaa");
2782       }
2783 
2784       bsp->seq_data = (SeqDataPtr) new_byte_store;
2785       bsp->seq_data_type = Seq_code_ncbistdaa;
2786       BSSeek((ByteStorePtr) bsp->seq_data, 0, SEEK_SET);
2787 
2788   }
2789 
2790   /* verify the input query is the same as the sequence
2791      within the checkpoint file */
2792 
2793   for (i = 0; i < compactSearch->qlength; i++) {
2794     c = BSGetByte((ByteStorePtr) bsp->seq_data);
2795     if (c == EOF) {
2796       ErrPostEx(SEV_WARNING, 0, 0, "Premature end of sequence data\n");
2797       PssmWithParametersFree(scoremat);
2798       return FALSE;
2799     }
2800     if (c != compactSearch->query[i]) {
2801       if (compactSearch->query[i] == Xchar) {
2802         ErrPostEx(SEV_WARNING, 0, 0, 
2803                      "Query sequence contains '%c' at position %d; "
2804                      "if filtering was used, rerun the search with "
2805                      "filtering turned off ('-F F')\n", getRes(Xchar), i);
2806       }
2807       else {
2808         ErrPostEx(SEV_WARNING, 0, 0, 
2809                      "Query sequence contains '%c' at position %d, "
2810                      "while sequence withing checkpoint file contains "
2811                      "'%c' at this position\n", 
2812                      getRes(compactSearch->query[i]), i, getRes(c));
2813       }
2814       PssmWithParametersFree(scoremat);
2815       return FALSE;
2816     }
2817   }
2818 
2819   /* Read in the frequency ratios, verify they fall
2820      in the correct range, and verify that the linked list
2821      of residue frequencies is exactly as long as it should be */
2822 
2823   freq_list = freqs->freqRatios;
2824   if (pssm->byRow == FALSE) {
2825     for (i = 0; i < pssm->numColumns; i++) {
2826       for (j = 0; j < pssm->numRows; j++) {
2827         if (freq_list == NULL)
2828           break;
2829         posSearch->posFreqs[i][j] = freq_list->data.realvalue;
2830 
2831         if (posSearch->posFreqs[i][j] < 0.0) {
2832           ErrPostEx(SEV_WARNING, 0, 0, "position frequency (%d,%d) "
2833                     "out of bounds\n", i, j);
2834           PssmWithParametersFree(scoremat);
2835           return FALSE;
2836         }
2837 
2838         freq_list = freq_list->next;
2839       }
2840       if (j < pssm->numRows)
2841         break;
2842     }
2843   }
2844   else {
2845     for (j = 0; j < pssm->numRows; j++) {
2846       for (i = 0; i < pssm->numColumns; i++) {
2847         if (freq_list == NULL)
2848           break;
2849         posSearch->posFreqs[i][j] = freq_list->data.realvalue;
2850 
2851         if (posSearch->posFreqs[i][j] < 0.0) {
2852           ErrPostEx(SEV_WARNING, 0, 0, "position frequency (%d,%d) "
2853                     "out of bounds\n", i, j);
2854           PssmWithParametersFree(scoremat);
2855           return FALSE;
2856         }
2857 
2858         freq_list = freq_list->next;
2859       }
2860       if (i < pssm->numColumns)
2861         break;
2862     }
2863   }
2864 
2865   if (i < pssm->numColumns || j < pssm->numRows) {
2866     ErrPostEx(SEV_WARNING, 0, 0, "Not enough frequency "
2867               "ratios in input scoremat\n");
2868     PssmWithParametersFree(scoremat);
2869     return FALSE;
2870   }
2871   if (freq_list != NULL) {
2872     ErrPostEx(SEV_WARNING, 0, 0, "Too many frequency "
2873               "ratios in input scoremat\n");
2874     PssmWithParametersFree(scoremat);
2875     return FALSE;
2876   }
2877   PssmWithParametersFree(scoremat);
2878   return TRUE;
2879 }
2880 
2881 static Boolean posReadPosFreqsStandard(posSearchItems * posSearch, compactSearchItems * compactSearch, CharPtr fileName, ValNodePtr * error_return)
2882 {
2883   FILE * checkFile; /*file in which to take the checkpoint*/
2884   Int4 length1, length2, c; /*length of query sequence, and an index for it*/
2885   Char  nextRes; /*next residue in stored copy of the query sequence*/
2886   Uint1Ptr oldQuery; /*array to hold the query sequence*/
2887 
2888   length1 = compactSearch->qlength;
2889 
2890   checkFile = FileOpen(fileName, "rb");  
2891   if (NULL == checkFile) {
2892     BlastConstructErrorMessage("posReadPosFreqsStandard", "Could not open checkpoint file\n", 1, error_return);
2893     return(FALSE);
2894   }
2895   getCkptInt4(length2,checkFile);
2896   if (length1 != length2) {
2897     ErrPostEx(SEV_WARNING, 0, 0, "Invalid usage of checkpoint recovery; old query has length %ld, new query has length %ld", (long) length2,  (long) length1);
2898     BlastConstructErrorMessage("posReadPosFreqsStandard", "Failed to recover data\n", 1, error_return);
2899     FileClose(checkFile);
2900     return(FALSE);
2901   }
2902   oldQuery = (Uint1Ptr) MemNew(length1 * sizeof(Uint1));
2903   if (NULL == oldQuery) {
2904     BlastConstructErrorMessage("posReadPosFreqsStandard", "Failed to reconstruct previous query\n", 1, error_return);
2905     BlastConstructErrorMessage("posReadPosFreqsStandard", "Failed to recover data\n", 1, error_return);
2906     FileClose(checkFile);
2907     return(FALSE);
2908   }  
2909   for(c = 0; c < length1; c++) {
2910     getCkptChar(nextRes, checkFile);
2911     oldQuery[c] = ResToInt(nextRes);
2912 
2913 
2914     if ((oldQuery[c] != compactSearch->query[c]) && (oldQuery[c] != Xchar)) {
2915                                 /* Error massage Added by Natsuhiko */
2916       if (compactSearch->query[c] == Xchar) {
2917         ErrPostEx(SEV_WARNING, 0, 0, "\nStored query has a %c at position %ld, while new query has a %c there.\n%c appears in query sequence: The query could be filtered. Run with \"-F F\" option to turn the filter off.",getRes(oldQuery[c]), (long) c, getRes(compactSearch->query[c]),
2918                   getRes(compactSearch->query[c]));
2919       }
2920       else{
2921       ErrPostEx(SEV_WARNING, 0, 0, "Stored query has a %c at position %ld, while new query has a %c there",getRes(oldQuery[c]), (long) c, getRes(compactSearch->query[c]));
2922       }
2923 
2924       BlastConstructErrorMessage("posReadPosFreqsStandard", "Failed to recover data\n", 1, error_return);
2925       MemFree(oldQuery);
2926       FileClose(checkFile);
2927       return(FALSE);
2928     }
2929     if ((oldQuery[c] != compactSearch->query[c]) && (Xchar==oldQuery[c])) {
2930       ErrPostEx(SEV_WARNING, 0, 0, "Stored query has a %c at position %ld, while new query has a %c there\n%c appears in the stored query: The stored query may be filtered. Run blastpgp with \"-F F\" option to turn the filter off",getRes(oldQuery[c]), (long) c,
2931                 getRes(compactSearch->query[c]), getRes(oldQuery[c])); }
2932 
2933   }
2934   getCkptFreqMatrix(posSearch->posFreqs,length1,compactSearch->alphabetSize,checkFile);
2935   MemFree(oldQuery);
2936   FileClose(checkFile);
2937   return(TRUE);
2938 }
2939 
2940 /*Read a checkpoint from the end of a previous PSI-BLAST round, get
2941 query length, query, and position-specific target frequencies.
2942 Returns TRUE if checkpoint was read sucessfully and FALSE otherwise. */
2943 Boolean LIBCALL  posReadCheckpoint(posSearchItems * posSearch, compactSearchItems * compactSearch, CharPtr fileName, Int4 scorematInput, ValNodePtr * error_return)
2944 {
2945   Int4 length1;    /*length of query sequence*/
2946   Int4 i,j;      /*indices for position and character in alphabet*/
2947   Boolean FreqsRead;
2948 
2949   BlastConstructErrorMessage("posReadCheckpoint", "Attempting to recover data from previous checkpoint\n", 1, error_return);
2950   length1 = compactSearch->qlength;
2951 
2952   /* allocate memory for the PSSMs and position frequency matrix */
2953 
2954   posSearch->posMatrix = (BLAST_Score **) MemNew((length1 + 1) * sizeof(BLAST_Score *));
2955   posSearch->posPrivateMatrix = (BLAST_Score **) MemNew((length1 + 1) * sizeof(BLAST_Score *));
2956   posSearch->posFreqs = (Nlm_FloatHi **) MemNew((length1 + 1) * sizeof(Nlm_FloatHi *));
2957   ASSERT(compactSearch->standardMatrixName);
2958   posSearch->stdFreqRatios =
2959            PSIMatrixFrequencyRatiosNew(compactSearch->standardMatrixName);
2960   if ((NULL == posSearch->posMatrix) || (NULL == posSearch->posPrivateMatrix) || (NULL == posSearch->posFreqs)) {
2961 
2962     BlastConstructErrorMessage("posReadCheckpoint", "Failed to allocate position-specific score matrix", 1, error_return);
2963     BlastConstructErrorMessage("posReadCheckpoint", "Failed to recover data\n", 1, error_return);
2964     return(FALSE);
2965   }
2966   for(i = 0; i <= length1; i++) {
2967     posSearch->posMatrix[i] = (BLAST_Score *) MemNew(compactSearch->alphabetSize * sizeof(BLAST_Score));
2968     posSearch->posPrivateMatrix[i] = (BLAST_Score *) MemNew(compactSearch->alphabetSize * sizeof(BLAST_Score));
2969     posSearch->posFreqs[i] = (Nlm_FloatHi *) MemNew(compactSearch->alphabetSize * sizeof(Nlm_FloatHi));
2970 
2971     if ((NULL == posSearch->posMatrix[i]) || (NULL == posSearch->posPrivateMatrix[i]) || (NULL == posSearch->posFreqs[i])) {
2972       BlastConstructErrorMessage("posReadCheckpoint", "Failed to allocate position-specific score matrix", 1, error_return);
2973       BlastConstructErrorMessage("posReadCheckpoint", "Failed to recover data\n", 1, error_return);
2974       return(FALSE);
2975     }
2976     for(j = 0; j < compactSearch->alphabetSize; j++) {
2977       posSearch->posFreqs[i][j] = 0.0;
2978     }
2979   }
2980 
2981   if (scorematInput == NO_SCOREMAT_IO) {
2982     FreqsRead = posReadPosFreqsStandard(posSearch, compactSearch, 
2983                       fileName, error_return);
2984   }
2985   else {
2986     FreqsRead = posReadPosFreqsScoremat(posSearch, compactSearch, 
2987                       fileName, scorematInput, error_return);
2988   }
2989   if (FreqsRead != TRUE) {
2990     BlastConstructErrorMessage("posReadCheckpoint", "Data recovery failed\n", 
2991                                                 1, error_return);
2992     return(FALSE);
2993   }
2994   posFreqsToInformation(posSearch,compactSearch);
2995   posFreqsToMatrix(posSearch,compactSearch);
2996   posScaling(posSearch, compactSearch);
2997   BlastConstructErrorMessage("posReadCheckpoint", "Data recovered successfully\n", 1, error_return);
2998   return(TRUE);
2999 }
3000 
3001 /* Two routines taken from */
3002 /* "p2c"  Copyright (C) 1989, 1990, 1991 Free Software Foundation.
3003  * By Dave Gillespie, daveg@csvax.cs.caltech.edu.  Version --VERSION--.
3004  * This file may be copied, modified, etc. in any way.  It is not restricted
3005  * by the licence agreement accompanying p2c itself.
3006  */
3007 
3008 
3009 /* Check if at end of file, using Pascal "eof" semantics.  End-of-file for
3010    stdin is broken; remove the special case for it to be broken in a
3011    different way. */
3012 
3013 static Int4 P_eof(FILE *f) 
3014 {
3015     register Int4 ch;
3016 
3017     if (feof(f))
3018         return 1;
3019     if (f == stdin)
3020         return 0;    /* not safe to look-ahead on the keyboard! */
3021     ch = getc(f);
3022     if (ch == EOF)
3023         return 1;
3024     ungetc(ch, f);
3025     return 0;
3026 }
3027 
3028 static Boolean isBlankChar(Char thisChar)
3029 {
3030   return((thisChar == ' ') || (thisChar == '\t') || (thisChar == '\n') ||
3031           (thisChar == '\t'));
3032 }
3033 
3034 
3035 /*preprocess alignment checkpoint file to find number of sequences and
3036 number of blocks. Return number of blocks as return value
3037 and number of sequences through a reference parameter*/
3038 static Int4 posFindAlignmentDimensions(char * fileName, Int4 *numSeqs, ValNodePtr * error_return)
3039 {
3040   FILE *checkFile;  /*checkpoint file*/
3041   Char nextLine[ALIGN_LINE_LENGTH];  /*line read in*/
3042   Boolean foundBlankLine; /*have we found a blank line yet*/
3043   Int4 numBlocks;  /*number of blocks to be returned*/
3044   Int4 testCountSeqs; /*counts number of sequences in each block
3045                         to ensure that each block has the same
3046                         number of sequences*/
3047    
3048   BlastConstructErrorMessage("posFindAlignmentDimensions", "Attempting to recover data from multiple alignment file\n", 1, error_return);
3049   checkFile = FileOpen(fileName, "rb");  
3050   if (NULL == checkFile) {
3051     ErrPostEx(SEV_WARNING, 0, 0, "\nCould not open alignment checkpoint file");
3052     BlastConstructErrorMessage("posFindAlignmentDimensions", "Could not open alignment checkpoint file\n", 1, error_return);
3053     return(0);
3054   }
3055   do {
3056     fgets(nextLine, ALIGN_LINE_LENGTH,checkFile);
3057   } while (isBlankChar(nextLine[0]));
3058   foundBlankLine = FALSE;
3059   *numSeqs = 1;
3060   numBlocks = 0;
3061   while (!P_eof(checkFile) && (!foundBlankLine)) {
3062     fgets(nextLine, ALIGN_LINE_LENGTH,checkFile);
3063     if (!(isBlankChar(nextLine[0])))
3064       (*numSeqs)++;
3065     else
3066       foundBlankLine = TRUE;
3067   }
3068   numBlocks = 1;
3069   while(!P_eof(checkFile)) {
3070     do {
3071       fgets(nextLine, ALIGN_LINE_LENGTH,checkFile);    
3072     } while((!P_eof(checkFile)) && (isBlankChar(nextLine[0])));
3073     if (!P_eof(checkFile)) {
3074       numBlocks++;
3075       testCountSeqs = 0;
3076     }    
3077     do {
3078       fgets(nextLine, ALIGN_LINE_LENGTH,checkFile);    
3079       testCountSeqs++;
3080     } while((!P_eof(checkFile)) && !(isBlankChar(nextLine[0])));
3081     if (!(isBlankChar(nextLine[0])))
3082       testCountSeqs++;
3083     if (testCountSeqs != (*numSeqs)) {
3084       ErrPostEx(SEV_WARNING, 0, 0, "\nInconsistent number of sequences across alignment blocks, first block has %d while block %d has %d sequences",(*numSeqs), numBlocks, testCountSeqs);
3085       BlastConstructErrorMessage("posFindAlignmentDimensions", "Could not read alignment due to different number of sequences in different blocks\n", 1, error_return);
3086       FileClose(checkFile);
3087       return(0);
3088     }
3089   }
3090 
3091   FileClose(checkFile);
3092   return(numBlocks);
3093 }
3094 
3095 /*Is thisChar possibly part of an alignment?*/
3096 static Boolean isProteinChar(Char thisChar)
3097 {
3098 
3099   return(((thisChar >= 'A') && (thisChar <= 'Z')) ||
3100          ((thisChar >= 'a') && (thisChar <= 'z')) ||
3101          ('-' == thisChar));
3102 }
3103 
3104 
3105 /*preprocess alignment checkpoint file to find the
3106 start column and end column of each alignment block.
3107 As a consequece the length of
3108 the alignment can be computed and it is returned*/
3109 static Int4 posPreprocessAlignment(char * fileName, Int4 numSeqs, Int4 numBlocks, Int4 * numCols, ValNodePtr * error_return)
3110 {
3111   FILE *checkFile;  /*checkpoint file*/
3112   char nextLine[ALIGN_LINE_LENGTH];  /*line read in*/
3113   Int4 alignLength; /*number of columns in alignment, to be returned*/
3114   Int4 charIndex; /*index over characters in a row*/
3115   Int4 blockIndex; /*index for the blocks in the alignment file*/
3116   Int4 seqIndex;
3117    
3118   checkFile = FileOpen(fileName, "rb");  
3119   if (NULL == checkFile) {
3120     ErrPostEx(SEV_WARNING, 0, 0, "\nCould not open alignment checkpoint file");
3121     BlastConstructErrorMessage("posPreprocessAlignment", "Could not open alignment checkpoint file\n", 1, error_return);
3122     return(0);
3123   }
3124 
3125   blockIndex = 0;
3126   alignLength= 0;
3127   while (!P_eof(checkFile)) {
3128     do {
3129       fgets(nextLine, ALIGN_LINE_LENGTH,checkFile);
3130     } while (isBlankChar(nextLine[0])); /*line belongs to query*/
3131     charIndex = 0;
3132     while(!(isBlankChar(nextLine[charIndex])))
3133       charIndex++;
3134     while(isBlankChar(nextLine[charIndex]))
3135       charIndex++;
3136     numCols[blockIndex] = 0;
3137     while (isProteinChar(nextLine[charIndex])){
3138       alignLength++;
3139       charIndex++;
3140       numCols[blockIndex]++;
3141     }
3142     /*skip over other sequences*/
3143     for (seqIndex = 0; seqIndex < numSeqs; seqIndex++) 
3144       fgets(nextLine, ALIGN_LINE_LENGTH,checkFile);
3145     blockIndex++;
3146   }
3147   FileClose(checkFile);
3148   return(alignLength);
3149 }
3150 
3151 /*Find the index of the sequence in the multiple alignment that
3152   matches the query sequence; if non match return -1*/
3153 static Int4 findQuery(posDesc ** alignArray, compactSearchItems * compactSearch, Int4 numSeqs, Int4 alignLength)
3154 {
3155    Uint1Ptr query; /*query sequence*/
3156    Int4 qlength;  /*length of query sequence*/
3157    Int4 seqIndex; /*index over sequences*/
3158    Int4 i;        /*index within a sequence*/
3159    Int4 queryIndex;  /*index within query*/
3160    Char thisRes;
3161 
3162    query = compactSearch->query;
3163    qlength = compactSearch->qlength;
3164    for(seqIndex = 0; seqIndex < numSeqs; seqIndex++) {
3165      i = 0;
3166      queryIndex = 0;
3167      while ((queryIndex < qlength) && (i < alignLength)) {
3168        if ('-' == alignArray[seqIndex][i].letter)
3169          i++;
3170        else {
3171          /*Need to keep lower-case letters*/
3172          thisRes = getRes(query[queryIndex]);
3173          /* Selenocysteines are replaced by X's in query; test for this
3174             possibility */
3175          if ((alignArray[seqIndex][i].letter == 'U' ||
3176              alignArray[seqIndex][i].letter == 'u') &&
3177              thisRes == 'X')
3178             thisRes = alignArray[seqIndex][i].letter;
3179             
3180          if ((thisRes != (alignArray[seqIndex][i].letter + 'A' - 'a')) &&
3181              (thisRes != alignArray[seqIndex][i].letter))
3182            /*character mismatch*/
3183            break;
3184          else {
3185            queryIndex++;
3186            i++;
3187          }
3188        }
3189      }
3190      if (queryIndex == qlength) {
3191        while (i < alignLength) {
3192          /*chew up gaps at end of alignment sequence*/
3193          if ('-' != alignArray[seqIndex][i].letter)
3194            break;
3195          i++;
3196        }
3197        /*found a match! */
3198        return(seqIndex);
3199      }
3200      else
3201        /*alignment string is prefix of query*/
3202        continue;
3203    }
3204    return (-1);
3205 
3206 }
3207 
3208 
3209 static posDesc** posReadAlignment(compactSearchItems *compactSearch, char * fileName, Int4 numSeqs, Int4 numBlocks, Int4 alignLength, Int4 * numCols,
3210 ValNodePtr * error_return)
3211 {
3212   FILE *checkFile; /*checkpoint file to read*/
3213   Char nextline[ALIGN_LINE_LENGTH];
3214   Int4 blockIndex;
3215   Int4 linePos; /* moving index for a line*/
3216   Int4 alignPos; /*placeholder for position alignment*/
3217   Int4 base; /*base for this block*/
3218   posDesc **returnArray; /*array of sequences to retunr*/
3219   Int4 i,j; /*loop indices*/
3220   Int4 temp; /*temporary character for swapping sequences*/
3221   Int4 queryIndex; /*which sequnec in the alignment is the query*/
3222 
3223   checkFile = FileOpen(fileName, "rb");  
3224   if (NULL == checkFile) {
3225     BlastConstructErrorMessage("posReadAlignment", "Could not open alignment checkpoint file\n", 1, error_return);
3226     ErrPostEx(SEV_WARNING, 0, 0, "\nCould not open alignment checkpoint file");
3227   }
3228   returnArray = (posDesc**) MemNew(numSeqs * sizeof(posDesc *));
3229   if (NULL == returnArray)
3230     exit(EXIT_FAILURE);
3231   for (i = 0; i < numSeqs; i++) {
3232     returnArray[i] = (posDesc *) MemNew(alignLength * sizeof(posDesc));
3233     if (NULL == returnArray[i])
3234       exit(EXIT_FAILURE);
3235     for(j = 0; j < alignLength; j++) {
3236       returnArray[i][j].letter = UNUSED;
3237       returnArray[i][j].used = FALSE;
3238     }
3239   }  
3240   alignPos = 0;
3241   base = 0;
3242   for(blockIndex = 0; blockIndex < numBlocks; blockIndex++){
3243     for(i = 0; i < numSeqs; i++) {
3244       do {
3245         fgets(nextline, ALIGN_LINE_LENGTH,checkFile);    
3246       } while(isBlankChar(nextline[0]));
3247       linePos = 0;
3248       while(!isBlankChar(nextline[linePos]))
3249         linePos++;
3250       while(isBlankChar(nextline[linePos]))
3251         linePos++;
3252       alignPos = base;
3253       while (alignPos < (base + numCols[blockIndex])) {
3254         if (!isProteinChar(nextline[linePos])) {
3255           BlastConstructErrorMessage("posReadAlignment", "Invalid character or wrong number of characters in a sequence\n", 1, error_return);
3256           ErrPostEx(SEV_WARNING, 0, 0, "\nInvalid character or wrong number of characters in sequence index %d\n", i+1);
3257         }
3258         returnArray[i][alignPos].letter = nextline[linePos];
3259         returnArray[i][alignPos].used = TRUE;
3260         alignPos++;
3261         linePos++;
3262       }
3263     }
3264     base += numCols[blockIndex];
3265   }
3266   FileClose(checkFile);
3267   queryIndex = findQuery(returnArray, compactSearch, numSeqs, alignLength);
3268   if (-1 == queryIndex) {
3269     BlastConstructErrorMessage("posReadAlignment", "None of the alignment sequences equals the query sequence\n", 1, error_return);
3270     ErrPostEx(SEV_WARNING, 0, 0, "\nNone of the alignment sequences equals the query sequence");
3271     BlastConstructErrorMessage("posReadAlignment", "Cannot recover alignment checkpoint\n", 1, error_return);
3272     ErrPostEx(SEV_WARNING, 0, 0, "\nCannot recover alignment checkpoint");
3273     exit(EXIT_FAILURE);
3274   }
3275   else {
3276     if (queryIndex > 0) {
3277       /*swap query with first sequence in alignment*/
3278       for (alignPos = 0; alignPos < alignLength; alignPos++) {
3279         temp = returnArray[0][alignPos].letter;
3280         returnArray[0][alignPos].letter = returnArray[queryIndex][alignPos].letter;
3281         returnArray[queryIndex][alignPos].letter = temp;
3282       }
3283     }
3284   }
3285   return(returnArray);
3286 }
3287 
3288 static void posProcessAlignment(posSearchItems *posSearch, compactSearchItems *compactSearch, char * fileName, Int4 numSeqs, Int4 numBlocks, Int4 alignLength, Int4 * numCols, ValNodePtr * error_return)
3289 {
3290   Int4 queryPos, alignPos, linePos; /*placeholder for position in query and
3291                              alignment*/
3292   Int4 *queryDesc; /*position correspondence between alignment and query*/
3293   Int4 seqIndex; /*counter for sequences*/
3294   posDesc ** alignArray;
3295   Int4 queryLength; /*length of query sequence*/
3296 
3297   alignArray = posReadAlignment(compactSearch, fileName, numSeqs,  numBlocks, alignLength, numCols, error_return);
3298   queryDesc = (Int4 *) MemNew(alignLength * sizeof(Int4));
3299   if (NULL == queryDesc)
3300     exit(EXIT_FAILURE);
3301   for(alignPos = 0; alignPos < alignLength; alignPos++)
3302     queryDesc[alignPos] = GAP_HERE;
3303   alignPos = 0;
3304   queryPos = 0;
3305   for(linePos = 0; linePos < alignLength; linePos++) {
3306     if (alignArray[0][linePos].letter == '-') 
3307       queryDesc[alignPos] = GAP_HERE;
3308     else {
3309       queryDesc[alignPos] = queryPos;
3310       if ((alignArray[0][linePos].letter >= 'A' ) && (alignArray[0][linePos].letter <= 'Z')) {
3311         posSearch->posDescMatrix[0][queryPos].letter = ResToInt(alignArray[0][linePos].letter);
3312         posSearch->posDescMatrix[0][queryPos].used = TRUE;
3313         posSearch->posDescMatrix[0][queryPos].e_value = compactSearch->ethresh/2;
3314         posSearch->posDescMatrix[0][queryPos].leftExtent = 0;
3315         posSearch->posDescMatrix[0][queryPos].rightExtent = compactSearch->qlength - 1;
3316         posSearch->posC[queryPos][ResToInt(alignArray[0][linePos].letter)]++;
3317         posSearch->posCount[queryPos]++;
3318       }
3319       else {
3320         posSearch->posDescMatrix[0][queryPos].used = FALSE;
3321         posSearch->posDescMatrix[0][queryPos].letter = ResToInt(alignArray[0][linePos].letter + 'A' - 'a');
3322       }
3323       queryPos++;
3324     }
3325     alignPos++;
3326   }
3327   queryLength = queryPos;
3328   for(seqIndex = 1; seqIndex < numSeqs; seqIndex++) {
3329     for(linePos = 0; linePos < alignLength; linePos++) {
3330       if (queryDesc[linePos] != GAP_HERE) {
3331         if (!(posSearch->posDescMatrix[0][queryDesc[linePos]].used)) {
3332           /*mark column as not participating*/
3333           posSearch->posDescMatrix[seqIndex][queryDesc[linePos]].used = FALSE;
3334         }
3335         else {
3336           posSearch->posDescMatrix[seqIndex][queryDesc[linePos]].letter = ResToInt(alignArray[seqIndex][linePos].letter);
3337           posSearch->posDescMatrix[seqIndex][queryDesc[linePos]].used = TRUE;
3338           posSearch->posDescMatrix[seqIndex][queryDesc[linePos]].e_value = compactSearch->ethresh/2;
3339           posSearch->posDescMatrix[seqIndex][queryDesc[linePos]].leftExtent = 0;
3340           posSearch->posDescMatrix[seqIndex][queryDesc[linePos]].rightExtent = compactSearch->qlength;
3341         }
3342       }
3343     }
3344   }
3345   /*make terminal gaps unused*/
3346   for(seqIndex = 1; seqIndex < numSeqs; seqIndex++) {
3347     linePos = 0;
3348     while((linePos < queryLength) && (posSearch->posDescMatrix[seqIndex][linePos].letter == GAP_CHAR)) {
3349       posSearch->posDescMatrix[seqIndex][linePos].used = FALSE;
3350       linePos++;
3351     }
3352     linePos = queryLength - 1;
3353     while((linePos >= 0) && (posSearch->posDescMatrix[seqIndex][linePos].letter == GAP_CHAR)) {
3354       posSearch->posDescMatrix[seqIndex][linePos].used = FALSE;
3355       linePos--;
3356     }
3357   }
3358   BlastConstructErrorMessage("posProcessAlignment", "Alignment recovered successfully\n", 1, error_return);
3359 }
3360 
3361 
3362 /* Top-level routine to compute position-specific matrix, when used for
3363 one round to recover from a multiple alignment checkpoint. */
3364 Int4Ptr * LIBCALL BposComputation(posSearchItems *posSearch, BlastSearchBlkPtr
3365    search, compactSearchItems * compactSearch, Char *ckptFileName, 
3366    Char *takeCkptFileName, Int4 scorematOutput, Bioseq *query_bsp,
3367    Int4 gap_open, Int4 gap_extend, ValNodePtr * error_return)
3368 {
3369   Int4 numSeqs, numBlocks, alignLength; /*number of sequences, number of pieces
3370                         of alignment, total length of the alignment*/
3371   Int4 *numCols;  /*number of columns within each block*/
3372 
3373   search->posConverged = FALSE;
3374 
3375   numBlocks = posFindAlignmentDimensions(ckptFileName, &numSeqs, error_return);
3376   if (0 == numBlocks) {
3377     ErrPostEx(SEV_WARNING, 0, 0, "\nCould not recover block structure from checkpoint");
3378     BlastConstructErrorMessage("BposComputation", "Cannot recover alignment checkpoint\n", 1, error_return);
3379     return(NULL);
3380   }
3381   numCols = (Int4 *) MemNew(numBlocks * sizeof(Int4));
3382   if (NULL == numCols)
3383     exit(EXIT_FAILURE);
3384   alignLength = posPreprocessAlignment(ckptFileName,  numSeqs, numBlocks,  numCols, error_return);
3385   if (0 == alignLength) {
3386     ErrPostEx(SEV_WARNING, 0, 0, "\nCould not recover alignment structure from checkpoint");
3387     BlastConstructErrorMessage("BposComputation", "Cannot recover alignment checkpoint\n", 1, error_return);
3388     return(NULL);
3389   } 
3390   posAllocateMemory(posSearch, compactSearch->alphabetSize, compactSearch->qlength, numSeqs);
3391   posProcessAlignment(posSearch, compactSearch, ckptFileName, numSeqs,  numBlocks, alignLength, numCols, error_return);
3392   MemFree(numCols);
3393   posSearch->posNumSequences = numSeqs;
3394   posPurgeMatches(posSearch, compactSearch, error_return);
3395   posComputeExtents(posSearch, compactSearch);
3396   posComputeSequenceWeights(posSearch, compactSearch, 1.0);
3397   posCheckWeights(posSearch, compactSearch);
3398   posSearch->posFreqs = posComputePseudoFreqs(posSearch, compactSearch, TRUE);
3399   if (NULL == search->sbp->posFreqs)
3400     search->sbp->posFreqs =  allocatePosFreqs(compactSearch->qlength, compactSearch->alphabetSize);
3401   copyPosFreqs(posSearch->posFreqs,search->sbp->posFreqs, compactSearch->qlength, compactSearch->alphabetSize);
3402   if (NULL != takeCkptFileName) {
3403     if (scorematOutput == NO_SCOREMAT_IO)
3404       posTakeCheckpoint(posSearch, compactSearch, takeCkptFileName, error_return);
3405     else
3406       posTakeScoremat(posSearch, compactSearch, takeCkptFileName, scorematOutput, query_bsp, gap_open, gap_extend, error_return);
3407   }
3408   posFreqsToMatrix(posSearch,compactSearch);
3409   posScaling(posSearch, compactSearch);
3410   return posSearch->posMatrix;
3411 }
3412 
3413 /****************************************************************************/
3414 /* PLEASE NOTE: The following structure and the PSIMatrixFrequencyRatios*
3415  * functions have been copied and renamed from
3416  * algo/blast/core/matrix_freq_ratios.[hc] to eliminate a dependency from the
3417  * ncbitool library to the blast library. 
3418  */
3419 #ifndef BLOSUM62_20A_SCALE_MULTIPLIER
3420 #define BLOSUM62_20A_SCALE_MULTIPLIER 0.9666
3421 #endif
3422 
3423 #ifndef BLOSUM62_20B_SCALE_MULTIPLIER
3424 #define BLOSUM62_20B_SCALE_MULTIPLIER 0.9344
3425 #endif
3426 
3427 /* posit.c has static frequency data for the 28 character alphabet,
3428  * which may be different from PROTEIN_ALPHABET */
3429 
3430 #define POSITAA_SIZE 28
3431 
3432 /** Underlying frequency ratios for BLOSUM45 */
3433 static const double BLOSUM45_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
3434 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3435   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3436   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3437   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3438   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3439   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3440   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
3441  {0.00000000e+00, 2.95043377e+00, 7.34701741e-01, 8.00397827e-01,
3442   6.88936672e-01, 8.25164920e-01, 5.87357723e-01, 1.08031132e+00,
3443   6.54086288e-01, 7.46806187e-01, 7.86209397e-01, 7.12370041e-01,
3444   8.21348665e-01, 7.89043130e-01, 7.08569419e-01, 8.66678731e-01,
3445   6.99695540e-01, 1.30031418e+00, 1.00058530e+00, 1.00992663e+00,
3446   5.65442334e-01, 7.50000000e-01, 6.38727873e-01, 8.41025176e-01,
3447   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.26064996e-01},
3448  {0.00000000e+00, 7.34701741e-01, 3.25946658e+00, 6.00232275e-01,
3449   3.59386786e+00, 1.30000108e+00, 4.95670856e-01, 8.85913772e-01,
3450   1.08769141e+00, 4.96979579e-01, 1.02264352e+00, 4.72210752e-01,
3451   5.80058073e-01, 2.86239890e+00, 6.85801186e-01, 9.91862879e-01,
3452   8.29088221e-01, 1.05297301e+00, 9.85207016e-01, 5.20111147e-01,
3453   3.80841719e-01, 7.50000000e-01, 6.27051284e-01, 1.18227759e+00,
3454   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.82061098e-01},
3455  {0.00000000e+00, 8.00397827e-01, 6.00232275e-01, 1.70900872e+01,
3456   5.32858023e-01, 5.45353890e-01, 6.01657157e-01, 5.56827599e-01,
3457   4.90637659e-01, 5.42801532e-01, 5.46735291e-01, 6.72663401e-01,
3458   6.03730225e-01, 6.80232381e-01, 4.11520916e-01, 4.86216592e-01,
3459   4.71814444e-01, 7.96941950e-01, 8.21766666e-01, 7.14771712e-01,
3460   3.33596922e-01, 7.50000000e-01, 4.88896599e-01, 5.22760621e-01,
3461   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 6.21018471e-01},
3462  {0.00000000e+00, 6.88936672e-01, 3.59386786e+00, 5.32858023e-01,
3463   5.35580571e+00, 1.64256912e+00, 4.31018420e-01, 7.40433725e-01,
3464   9.76205497e-01, 4.40334375e-01, 9.41681214e-01, 4.62523949e-01,
3465   4.94422549e-01, 1.50174498e+00, 7.24041930e-01, 9.57667486e-01,
3466   7.71179788e-01, 9.29413105e-01, 8.76125496e-01, 4.93585385e-01,
3467   3.73386452e-01, 7.50000000e-01, 6.44927232e-01, 1.38090402e+00,
3468   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.53699350e-01},
3469  {0.00000000e+00, 8.25164920e-01, 1.30000108e+00, 5.45353890e-01,
3470   1.64256912e+00, 3.87327599e+00, 4.97795679e-01, 5.76408577e-01,
3471   9.61718230e-01, 4.85270933e-01, 1.27686825e+00, 5.70784073e-01,
3472   6.14865688e-01, 8.93236200e-01, 9.10746443e-01, 1.53097375e+00,
3473   1.01074883e+00, 9.12113764e-01, 8.32873235e-01, 5.55160304e-01,
3474   5.19337483e-01, 7.50000000e-01, 6.16552718e-01, 2.97840479e+00,
3475   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.36776244e-01},
3476  {0.00000000e+00, 5.87357723e-01, 4.95670856e-01, 6.01657157e-01,
3477   4.31018420e-01, 4.97795679e-01, 5.74817622e+00, 4.80346092e-01,
3478   6.79103477e-01, 1.06375667e+00, 5.29188869e-01, 1.30295859e+00,
3479   1.06255416e+00, 5.72439082e-01, 4.51176385e-01, 4.43558969e-01,
3480   5.89537777e-01, 6.09495403e-01, 7.16103747e-01, 9.52475503e-01,
3481   1.35493791e+00, 7.50000000e-01, 2.18456832e+00, 4.77074668e-01,
3482   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 1.20783008e+00},
3483  {0.00000000e+00, 1.08031132e+00, 8.85913772e-01, 5.56827599e-01,
3484   7.40433725e-01, 5.76408577e-01, 4.80346092e-01, 5.07068525e+00,
3485   6.62087167e-01, 4.16341047e-01, 6.77879412e-01, 4.50091586e-01,
3486   5.84692214e-01, 1.05865660e+00, 7.02165561e-01, 6.87007231e-01,
3487   5.70228460e-01, 1.05800656e+00, 6.92819008e-01, 4.79214700e-01,
3488   5.91296285e-01, 7.50000000e-01, 5.49197180e-01, 6.18662539e-01,
3489   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.36669292e-01},
3490  {0.00000000e+00, 6.54086288e-01, 1.08769141e+00, 4.90637659e-01,
3491   9.76205497e-01, 9.61718230e-01, 6.79103477e-01, 6.62087167e-01,
3492   9.51252809e+00, 4.53313059e-01, 8.90272071e-01, 6.69868446e-01,
3493   9.18088604e-01, 1.22006964e+00, 6.61223470e-01, 1.15049417e+00,
3494   9.73045615e-01, 8.54331847e-01, 7.06245757e-01, 4.56693295e-01,
3495   4.51816356e-01, 7.50000000e-01, 1.47204221e+00, 1.03383965e+00,
3496   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.83746261e-01},
3497  {0.00000000e+00, 7.46806187e-01, 4.96979579e-01, 5.42801532e-01,
3498   4.40334375e-01, 4.85270933e-01, 1.06375667e+00, 4.16341047e-01,
3499   4.53313059e-01, 3.23256769e+00, 5.32316397e-01, 1.59618413e+00,
3500   1.45527106e+00, 5.64240025e-01, 6.09639867e-01, 5.77938325e-01,
3501   4.88387978e-01, 6.18410187e-01, 8.47505386e-01, 2.17596400e+00,
3502   5.64907506e-01, 7.50000000e-01, 9.06458192e-01, 5.20674297e-01,
3503   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 2.24695958e+00},
3504  {0.00000000e+00, 7.86209397e-01, 1.02264352e+00, 5.46735291e-01,
3505   9.41681214e-01, 1.27686825e+00, 5.29188869e-01, 6.77879412e-01,
3506   8.90272071e-01, 5.32316397e-01, 3.32707189e+00, 5.53563636e-01,
3507   7.37955763e-01, 1.11877807e+00, 7.81202774e-01, 1.33004839e+00,
3508   1.94261316e+00, 8.89937552e-01, 8.84562104e-01, 5.91651856e-01,
3509   5.61572955e-01, 7.50000000e-01, 7.37107274e-01, 1.29718560e+00,
3510   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.45113795e-01},
3511  {0.00000000e+00, 7.12370041e-01, 4.72210752e-01, 6.72663401e-01,
3512   4.62523949e-01, 5.70784073e-01, 1.30295859e+00, 4.50091586e-01,
3513   6.69868446e-01, 1.59618413e+00, 5.53563636e-01, 2.99708655e+00,
3514   1.73144954e+00, 4.83712850e-01, 4.77913692e-01, 6.42028706e-01,
3515   6.01135200e-01, 5.55659969e-01, 7.80723755e-01, 1.33363845e+00,
3516   6.70858407e-01, 7.50000000e-01, 9.65090110e-01, 5.98002922e-01,
3517   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 2.43995990e+00},
3518  {0.00000000e+00, 8.21348665e-01, 5.80058073e-01, 6.03730225e-01,
3519   4.94422549e-01, 6.14865688e-01, 1.06255416e+00, 5.84692214e-01,
3520   9.18088604e-01, 1.45527106e+00, 7.37955763e-01, 1.73144954e+00,
3521   4.11411354e+00, 6.81741591e-01, 6.43682874e-01, 9.40467390e-01,
3522   7.75906233e-01, 6.60370266e-01, 8.60449567e-01, 1.23582796e+00,
3523   6.34345311e-01, 7.50000000e-01, 1.02316322e+00, 7.39261071e-01,
3524   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 1.62161577e+00},
3525  {0.00000000e+00, 7.89043130e-01, 2.86239890e+00, 6.80232381e-01,
3526   1.50174498e+00, 8.93236200e-01, 5.72439082e-01, 1.05865660e+00,
3527   1.22006964e+00, 5.64240025e-01, 1.11877807e+00, 4.83712850e-01,
3528   6.81741591e-01, 4.47803773e+00, 6.40394172e-01, 1.03246645e+00,
3529   8.97848625e-01, 1.19968790e+00, 1.11473028e+00, 5.51607804e-01,
3530   3.89694095e-01, 7.50000000e-01, 6.05825405e-01, 9.46428796e-01,
3531   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.15737804e-01},
3532  {0.00000000e+00, 7.08569419e-01, 6.85801186e-01, 4.11520916e-01,
3533   7.24041930e-01, 9.10746443e-01, 4.51176385e-01, 7.02165561e-01,
3534   6.61223470e-01, 6.09639867e-01, 7.81202774e-01, 4.77913692e-01,
3535   6.43682874e-01, 6.40394172e-01, 8.81911509e+00, 7.15515810e-01,
3536   5.81631739e-01, 7.49733904e-01, 8.56242933e-01, 5.40037335e-01,
3537   5.25005050e-01, 7.50000000e-01, 4.78832406e-01, 8.36159027e-01,
3538   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.30300041e-01},
3539  {0.00000000e+00, 8.66678731e-01, 9.91862879e-01, 4.86216592e-01,
3540   9.57667486e-01, 1.53097375e+00, 4.43558969e-01, 6.87007231e-01,
3541   1.15049417e+00, 5.77938325e-01, 1.33004839e+00, 6.42028706e-01,
3542   9.40467390e-01, 1.03246645e+00, 7.15515810e-01, 4.40728842e+00,
3543   1.32912854e+00, 1.09183956e+00, 7.80601862e-01, 5.47266398e-01,
3544   6.45177884e-01, 7.50000000e-01, 8.29182983e-01, 2.62986317e+00,
3545   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 6.16540522e-01},
3546  {0.00000000e+00, 6.99695540e-01, 8.29088221e-01, 4.71814444e-01,
3547   7.71179788e-01, 1.01074883e+00, 5.89537777e-01, 5.70228460e-01,
3548   9.73045615e-01, 4.88387978e-01, 1.94261316e+00, 6.01135200e-01,
3549   7.75906233e-01, 8.97848625e-01, 5.81631739e-01, 1.32912854e+00,
3550   4.74702063e+00, 7.99048209e-01, 7.15164318e-01, 5.77699501e-01,
3551   5.80165842e-01, 7.50000000e-01, 8.07446927e-01, 1.13238507e+00,
3552   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.56296615e-01},
3553  {0.00000000e+00, 1.30031418e+00, 1.05297301e+00, 7.96941950e-01,
3554   9.29413105e-01, 9.12113764e-01, 6.09495403e-01, 1.05800656e+00,
3555   8.54331847e-01, 6.18410187e-01, 8.89937552e-01, 5.55659969e-01,
3556   6.60370266e-01, 1.19968790e+00, 7.49733904e-01, 1.09183956e+00,
3557   7.99048209e-01, 2.78188630e+00, 1.47248598e+00, 7.27836330e-01,
3558   4.28363793e-01, 7.50000000e-01, 7.05878947e-01, 9.80777594e-01,
3559   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.80615182e-01},
3560  {0.00000000e+00, 1.00058530e+00, 9.85207016e-01, 8.21766666e-01,
3561   8.76125496e-01, 8.32873235e-01, 7.16103747e-01, 6.92819008e-01,
3562   7.06245757e-01, 8.47505386e-01, 8.84562104e-01, 7.80723755e-01,
3563   8.60449567e-01, 1.11473028e+00, 8.56242933e-01, 7.80601862e-01,
3564   7.15164318e-01, 1.47248598e+00, 3.13871529e+00, 1.04019697e+00,
3565   4.54128072e-01, 7.50000000e-01, 7.43457494e-01, 8.12903077e-01,
3566   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 8.07282226e-01},
3567  {0.00000000e+00, 1.00992663e+00, 5.20111147e-01, 7.14771712e-01,
3568   4.93585385e-01, 5.55160304e-01, 9.52475503e-01, 4.79214700e-01,
3569   4.56693295e-01, 2.17596400e+00, 5.91651856e-01, 1.33363845e+00,
3570   1.23582796e+00, 5.51607804e-01, 5.40037335e-01, 5.47266398e-01,
3571   5.77699501e-01, 7.27836330e-01, 1.04019697e+00, 2.87075890e+00,
3572   4.73320057e-01, 7.50000000e-01, 8.09252575e-01, 5.52144455e-01,
3573   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 1.66862396e+00},
3574  {0.00000000e+00, 5.65442334e-01, 3.80841719e-01, 3.33596922e-01,
3575   3.73386452e-01, 5.19337483e-01, 1.35493791e+00, 5.91296285e-01,
3576   4.51816356e-01, 5.64907506e-01, 5.61572955e-01, 6.70858407e-01,
3577   6.34345311e-01, 3.89694095e-01, 5.25005050e-01, 6.45177884e-01,
3578   5.80165842e-01, 4.28363793e-01, 4.54128072e-01, 4.73320057e-01,
3579   2.97023509e+01, 7.50000000e-01, 1.80096028e+00, 5.67414520e-01,
3580   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 6.28722660e-01},
3581  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3582   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3583   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3584   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3585   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3586   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3587   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.50000000e-01},
3588  {0.00000000e+00, 6.38727873e-01, 6.27051284e-01, 4.88896599e-01,
3589   6.44927232e-01, 6.16552718e-01, 2.18456832e+00, 5.49197180e-01,
3590   1.47204221e+00, 9.06458192e-01, 7.37107274e-01, 9.65090110e-01,
3591   1.02316322e+00, 6.05825405e-01, 4.78832406e-01, 8.29182983e-01,
3592   8.07446927e-01, 7.05878947e-01, 7.43457494e-01, 8.09252575e-01,
3593   1.80096028e+00, 7.50000000e-01, 5.75351902e+00, 6.97787623e-01,
3594   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 9.41772708e-01},
3595  {0.00000000e+00, 8.41025176e-01, 1.18227759e+00, 5.22760621e-01,
3596   1.38090402e+00, 2.97840479e+00, 4.77074668e-01, 6.18662539e-01,
3597   1.03383965e+00, 5.20674297e-01, 1.29718560e+00, 5.98002922e-01,
3598   7.39261071e-01, 9.46428796e-01, 8.36159027e-01, 2.62986317e+00,
3599   1.13238507e+00, 9.80777594e-01, 8.12903077e-01, 5.52144455e-01,
3600   5.67414520e-01, 7.50000000e-01, 6.97787623e-01, 2.84524527e+00,
3601   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.67250003e-01},
3602  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3603   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3604   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3605   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3606   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3607   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3608   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.50000000e-01},
3609  {0.00000000e+00, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3610   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3611   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3612   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3613   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3614   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3615   2.90000000e-01, 1.33300000e+00, 2.90000000e-01, 2.90000000e-01},
3616  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3617   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3618   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3619   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3620   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3621   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3622   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.50000000e-01},
3623  {0.00000000e+00, 7.26064996e-01, 4.82061098e-01, 6.21018471e-01,
3624   4.53699350e-01, 5.36776244e-01, 1.20783008e+00, 4.36669292e-01,
3625   5.83746261e-01, 2.24695958e+00, 5.45113795e-01, 2.43995990e+00,
3626   1.62161577e+00, 5.15737804e-01, 5.30300041e-01, 6.16540522e-01,
3627   5.56296615e-01, 5.80615182e-01, 8.07282226e-01, 1.66862396e+00,
3628   6.28722660e-01, 7.50000000e-01, 9.41772708e-01, 5.67250003e-01,
3629   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 2.36320536e+00}};
3630 
3631 
3632 /** Underlying frequency ratios for BLOSUM50 */
3633 static const double BLOSUM50_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
3634 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3635   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3636   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3637   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3638   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3639   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3640   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
3641  {0.00000000e+00, 3.27354473e+00, 6.87168642e-01, 8.87624875e-01,
3642   6.59704230e-01, 7.97359654e-01, 5.46298170e-01, 1.10130683e+00,
3643   6.41220589e-01, 7.15157692e-01, 7.47622201e-01, 6.56954186e-01,
3644   8.53472686e-01, 7.19514908e-01, 7.14770771e-01, 8.19913708e-01,
3645   6.68351460e-01, 1.36359270e+00, 9.67331593e-01, 9.81625416e-01,
3646   4.63560176e-01, 7.50000000e-01, 5.96400452e-01, 8.05980349e-01,
3647   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 6.80310043e-01},
3648  {0.00000000e+00, 6.87168642e-01, 3.67565906e+00, 5.07294595e-01,
3649   4.02052534e+00, 1.31892999e+00, 3.83849184e-01, 8.47577177e-01,
3650   1.11810068e+00, 4.07212168e-01, 9.68440788e-01, 3.91166888e-01,
3651   5.16058658e-01, 3.26949213e+00, 6.61247189e-01, 9.98204754e-01,
3652   7.59007679e-01, 1.06055276e+00, 9.55438618e-01, 4.46192804e-01,
3653   3.38571955e-01, 7.50000000e-01, 5.55905269e-01, 1.19634119e+00,
3654   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 3.97605526e-01},
3655  {0.00000000e+00, 8.87624875e-01, 5.07294595e-01, 1.82308935e+01,
3656   4.27724382e-01, 4.56030174e-01, 5.64985221e-01, 5.24350848e-01,
3657   5.17412429e-01, 5.87186086e-01, 4.59864212e-01, 6.50074165e-01,
3658   6.80946766e-01, 6.01008569e-01, 4.03060607e-01, 4.81296027e-01,
3659   4.27834290e-01, 8.29850973e-01, 8.17890869e-01, 8.08665030e-01,
3660   3.12131245e-01, 7.50000000e-01, 5.38704705e-01, 4.65687383e-01,
3661   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 6.24838486e-01},
3662  {0.00000000e+00, 6.59704230e-01, 4.02052534e+00, 4.27724382e-01,
3663   6.11147890e+00, 1.65784569e+00, 3.37276799e-01, 7.44468416e-01,
3664   8.83789762e-01, 3.70146565e-01, 8.90348134e-01, 3.72923686e-01,
3665   4.35009775e-01, 1.55790069e+00, 7.09628659e-01, 9.66997497e-01,
3666   6.78533894e-01, 9.21480865e-01, 8.25179634e-01, 4.31712984e-01,
3667   3.07050170e-01, 7.50000000e-01, 5.04473723e-01, 1.39378711e+00,
3668   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 3.71809285e-01},
3669  {0.00000000e+00, 7.97359654e-01, 1.31892999e+00, 4.56030174e-01,
3670   1.65784569e+00, 4.43735647e+00, 4.56055858e-01, 5.39909105e-01,
3671   9.11487897e-01, 4.15558851e-01, 1.33108575e+00, 4.78428941e-01,
3672   6.05096970e-01, 9.19771370e-01, 8.38805682e-01, 1.67134451e+00,
3673   9.76357610e-01, 8.82100970e-01, 8.19031320e-01, 4.79075838e-01,
3674   5.48039829e-01, 7.50000000e-01, 6.51686488e-01, 3.38012103e+00,
3675   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.53200481e-01},
3676  {0.00000000e+00, 5.46298170e-01, 3.83849184e-01, 5.64985221e-01,
3677   3.37276799e-01, 4.56055858e-01, 6.63625360e+00, 4.13949535e-01,
3678   7.54714659e-01, 9.89742646e-01, 4.44979578e-01, 1.26171801e+00,
3679   1.05158910e+00, 4.38699901e-01, 3.75736079e-01, 4.16967765e-01,
3680   4.61789222e-01, 5.52981315e-01, 5.70349305e-01, 8.59643167e-01,
3681   1.34807169e+00, 7.50000000e-01, 2.42442622e+00, 4.41115461e-01,
3682   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 1.15257995e+00},
3683  {0.00000000e+00, 1.10130683e+00, 8.47577177e-01, 5.24350848e-01,
3684   7.44468416e-01, 5.39909105e-01, 4.13949535e-01, 5.79218671e+00,
3685   6.01271290e-01, 3.70370366e-01, 6.54870319e-01, 3.76903001e-01,
3686   5.19438610e-01, 9.69013722e-01, 6.20168128e-01, 6.41416113e-01,
3687   5.16985831e-01, 9.99248542e-01, 6.36269018e-01, 4.02720033e-01,
3688   5.04888636e-01, 7.50000000e-01, 4.67274430e-01, 5.78707493e-01,
3689   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 3.74281590e-01},
3690  {0.00000000e+00, 6.41220589e-01, 1.11810068e+00, 5.17412429e-01,
3691   8.83789762e-01, 9.11487897e-01, 7.54714659e-01, 6.01271290e-01,
3692   1.04489376e+01, 4.11545408e-01, 9.45545516e-01, 5.47445792e-01,
3693   7.60124356e-01, 1.39406083e+00, 5.81906417e-01, 1.20911332e+00,
3694   9.81604707e-01, 8.22540644e-01, 6.52641826e-01, 4.13620259e-01,
3695   4.75002356e-01, 7.50000000e-01, 1.57000854e+00, 1.02524740e+00,
3696   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.92911793e-01},
3697  {0.00000000e+00, 7.15157692e-01, 4.07212168e-01, 5.87186086e-01,
3698   3.70146565e-01, 4.15558851e-01, 9.89742646e-01, 3.70370366e-01,
3699   4.11545408e-01, 3.41093885e+00, 4.68297844e-01, 1.69677965e+00,
3700   1.43810563e+00, 4.50866254e-01, 5.11210841e-01, 5.02656404e-01,
3701   4.35318230e-01, 5.45643330e-01, 8.60722536e-01, 2.31272269e+00,
3702   5.22495607e-01, 7.50000000e-01, 8.26095669e-01, 4.48849604e-01,
3703   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 2.38463611e+00},
3704  {0.00000000e+00, 7.47622201e-01, 9.68440788e-01, 4.59864212e-01,
3705   8.90348134e-01, 1.33108575e+00, 4.44979578e-01, 6.54870319e-01,
3706   9.45545516e-01, 4.68297844e-01, 3.88090096e+00, 4.79194854e-01,
3707   6.85231759e-01, 1.06041456e+00, 7.63679086e-01, 1.41855717e+00,
3708   2.06468049e+00, 8.92977250e-01, 8.44796364e-01, 5.22802406e-01,
3709   4.61593643e-01, 7.50000000e-01, 6.67754286e-01, 1.36451940e+00,
3710   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.74822110e-01},
3711  {0.00000000e+00, 6.56954186e-01, 3.91166888e-01, 6.50074165e-01,
3712   3.72923686e-01, 4.78428941e-01, 1.26171801e+00, 3.76903001e-01,
3713   5.47445792e-01, 1.69677965e+00, 4.79194854e-01, 3.32815910e+00,
3714   1.78991633e+00, 4.12652855e-01, 4.43674459e-01, 5.62937315e-01,
3715   5.54029894e-01, 5.10605044e-01, 7.59171671e-01, 1.32427289e+00,
3716   6.01518374e-01, 7.50000000e-01, 8.58373419e-01, 5.10730048e-01,
3717   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 2.67352044e+00},
3718  {0.00000000e+00, 8.53472686e-01, 5.16058658e-01, 6.80946766e-01,
3719   4.35009775e-01, 6.05096970e-01, 1.05158910e+00, 5.19438610e-01,
3720   7.60124356e-01, 1.43810563e+00, 6.85231759e-01, 1.78991633e+00,
3721   4.81561797e+00, 6.11514139e-01, 5.44813932e-01, 9.59915799e-01,
3722   6.78015272e-01, 6.82291911e-01, 8.82308943e-01, 1.21329921e+00,
3723   7.61522900e-01, 7.50000000e-01, 9.17831903e-01, 7.40717150e-01,
3724   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 1.64874201e+00},
3725  {0.00000000e+00, 7.19514908e-01, 3.26949213e+00, 6.01008569e-01,
3726   1.55790069e+00, 9.19771370e-01, 4.38699901e-01, 9.69013722e-01,
3727   1.39406083e+00, 4.50866254e-01, 1.06041456e+00, 4.12652855e-01,
3728   6.11514139e-01, 5.28532229e+00, 6.04265819e-01, 1.03495916e+00,
3729   8.53785837e-01, 1.22434496e+00, 1.10885139e+00, 4.63246441e-01,
3730   3.75696800e-01, 7.50000000e-01, 6.16478872e-01, 9.63798879e-01,
3731   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.27987098e-01},
3732  {0.00000000e+00, 7.14770771e-01, 6.61247189e-01, 4.03060607e-01,
3733   7.09628659e-01, 8.38805682e-01, 3.75736079e-01, 6.20168128e-01,
3734   5.81906417e-01, 5.11210841e-01, 7.63679086e-01, 4.43674459e-01,
3735   5.44813932e-01, 6.04265819e-01, 1.02035160e+01, 7.50499600e-01,
3736   5.18638945e-01, 7.59438841e-01, 7.48565360e-01, 5.24438149e-01,
3737   4.20092966e-01, 7.50000000e-01, 4.68173126e-01, 8.05053001e-01,
3738   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.70775405e-01},
3739  {0.00000000e+00, 8.19913708e-01, 9.98204754e-01, 4.81296027e-01,
3740   9.66997497e-01, 1.67134451e+00, 4.16967765e-01, 6.41416113e-01,
3741   1.20911332e+00, 5.02656404e-01, 1.41855717e+00, 5.62937315e-01,
3742   9.59915799e-01, 1.03495916e+00, 7.50499600e-01, 4.69722165e+00,
3743   1.35733364e+00, 1.06872445e+00, 8.10316946e-01, 5.57384267e-01,
3744   7.14705591e-01, 7.50000000e-01, 7.42076535e-01, 2.82790659e+00,
3745   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.38747839e-01},
3746  {0.00000000e+00, 6.68351460e-01, 7.59007679e-01, 4.27834290e-01,
3747   6.78533894e-01, 9.76357610e-01, 4.61789222e-01, 5.16985831e-01,
3748   9.81604707e-01, 4.35318230e-01, 2.06468049e+00, 5.54029894e-01,
3749   6.78015272e-01, 8.53785837e-01, 5.18638945e-01, 1.35733364e+00,
3750   5.37787401e+00, 8.04499038e-01, 7.36510915e-01, 5.12488758e-01,
3751   5.28823677e-01, 7.50000000e-01, 7.27125062e-01, 1.12197569e+00,
3752   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.06393371e-01},
3753  {0.00000000e+00, 1.36359270e+00, 1.06055276e+00, 8.29850973e-01,
3754   9.21480865e-01, 8.82100970e-01, 5.52981315e-01, 9.99248542e-01,
3755   8.22540644e-01, 5.45643330e-01, 8.92977250e-01, 5.10605044e-01,
3756   6.82291911e-01, 1.22434496e+00, 7.59438841e-01, 1.06872445e+00,
3757   8.04499038e-01, 3.14298812e+00, 1.49727124e+00, 6.78664919e-01,
3758   3.92328021e-01, 7.50000000e-01, 6.51019697e-01, 9.53432893e-01,
3759   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.24665180e-01},
3760  {0.00000000e+00, 9.67331593e-01, 9.55438618e-01, 8.17890869e-01,
3761   8.25179634e-01, 8.19031320e-01, 5.70349305e-01, 6.36269018e-01,
3762   6.52641826e-01, 8.60722536e-01, 8.44796364e-01, 7.59171671e-01,
3763   8.82308943e-01, 1.10885139e+00, 7.48565360e-01, 8.10316946e-01,
3764   7.36510915e-01, 1.49727124e+00, 3.55307500e+00, 1.05992520e+00,
3765   5.02669810e-01, 7.50000000e-01, 6.90730891e-01, 8.15700480e-01,
3766   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.99921922e-01},
3767  {0.00000000e+00, 9.81625416e-01, 4.46192804e-01, 8.08665030e-01,
3768   4.31712984e-01, 4.79075838e-01, 8.59643167e-01, 4.02720033e-01,
3769   4.13620259e-01, 2.31272269e+00, 5.22802406e-01, 1.32427289e+00,
3770   1.21329921e+00, 4.63246441e-01, 5.24438149e-01, 5.57384267e-01,
3771   5.12488758e-01, 6.78664919e-01, 1.05992520e+00, 3.11745700e+00,
3772   4.84839541e-01, 7.50000000e-01, 7.27350506e-01, 5.09007179e-01,
3773   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 1.72091725e+00},
3774  {0.00000000e+00, 4.63560176e-01, 3.38571955e-01, 3.12131245e-01,
3775   3.07050170e-01, 5.48039829e-01, 1.34807169e+00, 5.04888636e-01,
3776   4.75002356e-01, 5.22495607e-01, 4.61593643e-01, 6.01518374e-01,
3777   7.61522900e-01, 3.75696800e-01, 4.20092966e-01, 7.14705591e-01,
3778   5.28823677e-01, 3.92328021e-01, 5.02669810e-01, 4.84839541e-01,
3779   3.13609332e+01, 7.50000000e-01, 1.76515899e+00, 6.11743441e-01,
3780   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 5.69808181e-01},
3781  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3782   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3783   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3784   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3785   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3786   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3787   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.50000000e-01},
3788  {0.00000000e+00, 5.96400452e-01, 5.55905269e-01, 5.38704705e-01,
3789   5.04473723e-01, 6.51686488e-01, 2.42442622e+00, 4.67274430e-01,
3790   1.57000854e+00, 8.26095669e-01, 6.67754286e-01, 8.58373419e-01,
3791   9.17831903e-01, 6.16478872e-01, 4.68173126e-01, 7.42076535e-01,
3792   7.27125062e-01, 6.51019697e-01, 6.90730891e-01, 7.27350506e-01,
3793   1.76515899e+00, 7.50000000e-01, 6.89283261e+00, 6.86235710e-01,
3794   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 8.45421029e-01},
3795  {0.00000000e+00, 8.05980349e-01, 1.19634119e+00, 4.65687383e-01,
3796   1.39378711e+00, 3.38012103e+00, 4.41115461e-01, 5.78707493e-01,
3797   1.02524740e+00, 4.48849604e-01, 1.36451940e+00, 5.10730048e-01,
3798   7.40717150e-01, 9.63798879e-01, 8.05053001e-01, 2.82790659e+00,
3799   1.12197569e+00, 9.53432893e-01, 8.15700480e-01, 5.09007179e-01,
3800   6.11743441e-01, 7.50000000e-01, 6.86235710e-01, 3.16905156e+00,
3801   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 4.85898712e-01},
3802  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3803   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3804   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3805   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3806   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3807   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3808   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.50000000e-01},
3809  {0.00000000e+00, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3810   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3811   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3812   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3813   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3814   2.90000000e-01, 2.90000000e-01, 2.90000000e-01, 2.90000000e-01,
3815   2.90000000e-01, 1.33300000e+00, 2.90000000e-01, 2.90000000e-01},
3816  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3817   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3818   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3819   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3820   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3821   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3822   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 7.50000000e-01},
3823  {0.00000000e+00, 6.80310043e-01, 3.97605526e-01, 6.24838486e-01,
3824   3.71809285e-01, 4.53200481e-01, 1.15257995e+00, 3.74281590e-01,
3825   4.92911793e-01, 2.38463611e+00, 4.74822110e-01, 2.67352044e+00,
3826   1.64874201e+00, 4.27987098e-01, 4.70775405e-01, 5.38747839e-01,
3827   5.06393371e-01, 5.24665180e-01, 7.99921922e-01, 1.72091725e+00,
3828   5.69808181e-01, 7.50000000e-01, 8.45421029e-01, 4.85898712e-01,
3829   7.50000000e-01, 2.90000000e-01, 7.50000000e-01, 2.55759716e+00}};
3830 
3831 
3832 /** Underlying frequency ratios for BLOSUM62 */
3833 static const double BLOSUM62_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
3834 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3835   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3836   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3837   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3838   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3839   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
3840   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
3841  {0.00000000e+00, 3.90294070e+00, 5.64459671e-01, 8.67987664e-01,
3842   5.44605275e-01, 7.41264113e-01, 4.64893827e-01, 1.05686961e+00,
3843   5.69364849e-01, 6.32481035e-01, 7.75390239e-01, 6.01945975e-01,
3844   7.23150342e-01, 5.88307640e-01, 7.54121369e-01, 7.56803943e-01,
3845   6.12698600e-01, 1.47210399e+00, 9.84401956e-01, 9.36458396e-01,
3846   4.16548781e-01, 7.50000000e-01, 5.42611869e-01, 7.47274948e-01,
3847   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 6.14377313e-01},
3848  {0.00000000e+00, 5.64459671e-01, 4.43758048e+00, 3.45226274e-01,
3849   4.74290926e+00, 1.33503378e+00, 3.24101420e-01, 7.38524318e-01,
3850   9.25449581e-01, 3.33981361e-01, 8.54849426e-01, 2.97257620e-01,
3851   4.04640322e-01, 4.07083696e+00, 5.53838329e-01, 9.44103648e-01,
3852   7.02873767e-01, 1.05798620e+00, 8.26250098e-01, 3.51280513e-01,
3853   2.52855433e-01, 7.50000000e-01, 4.09444638e-01, 1.18382127e+00,
3854   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 3.12208474e-01},
3855  {0.00000000e+00, 8.67987664e-01, 3.45226274e-01, 1.95765857e+01,
3856   3.01454345e-01, 2.85934574e-01, 4.38990118e-01, 4.20387870e-01,
3857   3.55049505e-01, 6.53458801e-01, 3.49128465e-01, 6.42275633e-01,
3858   6.11354340e-01, 3.97802620e-01, 3.79562691e-01, 3.65781531e-01,
3859   3.08939296e-01, 7.38415701e-01, 7.40551692e-01, 7.55844055e-01,
3860   4.49983903e-01, 7.50000000e-01, 4.34203398e-01, 3.16819526e-01,
3861   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 6.46828489e-01},
3862  {0.00000000e+00, 5.44605275e-01, 4.74290926e+00, 3.01454345e-01,
3863   7.39792738e+00, 1.68781075e+00, 2.98969081e-01, 6.34301019e-01,
3864   6.78558839e-01, 3.39015407e-01, 7.84090406e-01, 2.86613046e-01,
3865   3.46454634e-01, 1.55385281e+00, 5.98716826e-01, 8.97081129e-01,
3866   5.73200024e-01, 9.13504624e-01, 6.94789868e-01, 3.36500142e-01,
3867   2.32102315e-01, 7.50000000e-01, 3.45683565e-01, 1.38195506e+00,
3868   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 3.07946931e-01},
3869  {0.00000000e+00, 7.41264113e-01, 1.33503378e+00, 2.85934574e-01,
3870   1.68781075e+00, 5.46952608e+00, 3.30743991e-01, 4.81267655e-01,
3871   9.60040718e-01, 3.30522558e-01, 1.30827885e+00, 3.72873704e-01,
3872   5.00342289e-01, 9.11298183e-01, 6.79202587e-01, 1.90173784e+00,
3873   9.60797602e-01, 9.50357185e-01, 7.41425610e-01, 4.28943130e-01,
3874   3.74300212e-01, 7.50000000e-01, 4.96467354e-01, 4.08949895e+00,
3875   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 3.55631838e-01},
3876  {0.00000000e+00, 4.64893827e-01, 3.24101420e-01, 4.38990118e-01,
3877   2.98969081e-01, 3.30743991e-01, 8.12879702e+00, 3.40640908e-01,
3878   6.51990521e-01, 9.45769883e-01, 3.44043119e-01, 1.15459749e+00,
3879   1.00437163e+00, 3.54288952e-01, 2.87444758e-01, 3.33972402e-01,
3880   3.80726330e-01, 4.39973597e-01, 4.81693683e-01, 7.45089738e-01,
3881   1.37437942e+00, 7.50000000e-01, 2.76938063e+00, 3.31992746e-01,
3882   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 1.06958025e+00},
3883  {0.00000000e+00, 1.05686961e+00, 7.38524318e-01, 4.20387870e-01,
3884   6.34301019e-01, 4.81267655e-01, 3.40640908e-01, 6.87630691e+00,
3885   4.92966576e-01, 2.75009722e-01, 5.88871736e-01, 2.84504012e-01,
3886   3.95486600e-01, 8.63711406e-01, 4.77385507e-01, 5.38649627e-01,
3887   4.49983999e-01, 9.03596525e-01, 5.79271582e-01, 3.36954912e-01,
3888   4.21690355e-01, 7.50000000e-01, 3.48714366e-01, 5.03463109e-01,
3889   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 2.80638726e-01},
3890  {0.00000000e+00, 5.69364849e-01, 9.25449581e-01, 3.55049505e-01,
3891   6.78558839e-01, 9.60040718e-01, 6.51990521e-01, 4.92966576e-01,
3892   1.35059997e+01, 3.26288125e-01, 7.78887490e-01, 3.80675486e-01,
3893   5.84132623e-01, 1.22200067e+00, 4.72879831e-01, 1.16798104e+00,
3894   9.17048021e-01, 7.36731740e-01, 5.57503254e-01, 3.39447442e-01,
3895   4.44088955e-01, 7.50000000e-01, 1.79790413e+00, 1.04047242e+00,
3896   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 3.58533474e-01},
3897  {0.00000000e+00, 6.32481035e-01, 3.33981361e-01, 6.53458801e-01,
3898   3.39015407e-01, 3.30522558e-01, 9.45769883e-01, 2.75009722e-01,
3899   3.26288125e-01, 3.99792994e+00, 3.96372934e-01, 1.69443475e+00,
3900   1.47774450e+00, 3.27934752e-01, 3.84662860e-01, 3.82937802e-01,
3901   3.54751311e-01, 4.43163582e-01, 7.79816110e-01, 2.41751209e+00,
3902   4.08874390e-01, 7.50000000e-01, 6.30388931e-01, 3.50796872e-01,
3903   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 2.63222650e+00},
3904  {0.00000000e+00, 7.75390239e-01, 8.54849426e-01, 3.49128465e-01,
3905   7.84090406e-01, 1.30827885e+00, 3.44043119e-01, 5.88871736e-01,
3906   7.78887490e-01, 3.96372934e-01, 4.76433717e+00, 4.28270363e-01,
3907   6.25302816e-01, 9.39841129e-01, 7.03774479e-01, 1.55432308e+00,
3908   2.07680867e+00, 9.31919141e-01, 7.92905803e-01, 4.56542720e-01,
3909   3.58930071e-01, 7.50000000e-01, 5.32179333e-01, 1.40344922e+00,
3910   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 4.15284382e-01},
3911  {0.00000000e+00, 6.01945975e-01, 2.97257620e-01, 6.42275633e-01,
3912   2.86613046e-01, 3.72873704e-01, 1.15459749e+00, 2.84504012e-01,
3913   3.80675486e-01, 1.69443475e+00, 4.28270363e-01, 3.79662137e+00,
3914   1.99429557e+00, 3.10043276e-01, 3.71121724e-01, 4.77325586e-01,
3915   4.73919278e-01, 4.28893743e-01, 6.60328975e-01, 1.31423573e+00,
3916   5.68037074e-01, 7.50000000e-01, 6.92059423e-01, 4.13275887e-01,
3917   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 2.94078574e+00},
3918  {0.00000000e+00, 7.23150342e-01, 4.04640322e-01, 6.11354340e-01,
3919   3.46454634e-01, 5.00342289e-01, 1.00437163e+00, 3.95486600e-01,
3920   5.84132623e-01, 1.47774450e+00, 6.25302816e-01, 1.99429557e+00,
3921   6.48145121e+00, 4.74529655e-01, 4.23898024e-01, 8.64250293e-01,
3922   6.22623369e-01, 5.98558924e-01, 7.93801616e-01, 1.26893679e+00,
3923   6.10296214e-01, 7.50000000e-01, 7.08364628e-01, 6.41102583e-01,
3924   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 1.78399892e+00},
3925  {0.00000000e+00, 5.88307640e-01, 4.07083696e+00, 3.97802620e-01,
3926   1.55385281e+00, 9.11298183e-01, 3.54288952e-01, 8.63711406e-01,
3927   1.22200067e+00, 3.27934752e-01, 9.39841129e-01, 3.10043276e-01,
3928   4.74529655e-01, 7.09409488e+00, 4.99932836e-01, 1.00058442e+00,
3929   8.58630478e-01, 1.23152924e+00, 9.84152635e-01, 3.69033853e-01,
3930   2.77782896e-01, 7.50000000e-01, 4.86030806e-01, 9.45834265e-01,
3931   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 3.17327197e-01},
3932  {0.00000000e+00, 7.54121369e-01, 5.53838329e-01, 3.79562691e-01,
3933   5.98716826e-01, 6.79202587e-01, 2.87444758e-01, 4.77385507e-01,
3934   4.72879831e-01, 3.84662860e-01, 7.03774479e-01, 3.71121724e-01,
3935   4.23898024e-01, 4.99932836e-01, 1.28375437e+01, 6.41280589e-01,
3936   4.81534905e-01, 7.55503259e-01, 6.88897122e-01, 4.43082984e-01,
3937   2.81833164e-01, 7.50000000e-01, 3.63521119e-01, 6.64534287e-01,
3938   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 3.76634549e-01},
3939  {0.00000000e+00, 7.56803943e-01, 9.44103648e-01, 3.65781531e-01,
3940   8.97081129e-01, 1.90173784e+00, 3.33972402e-01, 5.38649627e-01,
3941   1.16798104e+00, 3.82937802e-01, 1.55432308e+00, 4.77325586e-01,
3942   8.64250293e-01, 1.00058442e+00, 6.41280589e-01, 6.24442175e+00,
3943   1.40579606e+00, 9.65555228e-01, 7.91320741e-01, 4.66777931e-01,
3944   5.09360272e-01, 7.50000000e-01, 6.11094097e-01, 3.58149606e+00,
3945   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 4.38898727e-01},
3946  {0.00000000e+00, 6.12698600e-01, 7.02873767e-01, 3.08939296e-01,
3947   5.73200024e-01, 9.60797602e-01, 3.80726330e-01, 4.49983999e-01,
3948   9.17048021e-01, 3.54751311e-01, 2.07680867e+00, 4.73919278e-01,
3949   6.22623369e-01, 8.58630478e-01, 4.81534905e-01, 1.40579606e+00,
3950   6.66557707e+00, 7.67165633e-01, 6.77754679e-01, 4.20072316e-01,
3951   3.95102106e-01, 7.50000000e-01, 5.55965425e-01, 1.13292384e+00,
3952   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 4.25403989e-01},
3953  {0.00000000e+00, 1.47210399e+00, 1.05798620e+00, 7.38415701e-01,
3954   9.13504624e-01, 9.50357185e-01, 4.39973597e-01, 9.03596525e-01,
3955   7.36731740e-01, 4.43163582e-01, 9.31919141e-01, 4.28893743e-01,
3956   5.98558924e-01, 1.23152924e+00, 7.55503259e-01, 9.65555228e-01,
3957   7.67165633e-01, 3.84284741e+00, 1.61392097e+00, 5.65223766e-01,
3958   3.85303035e-01, 7.50000000e-01, 5.57520051e-01, 9.56235816e-01,
3959   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 4.34703235e-01},
3960  {0.00000000e+00, 9.84401956e-01, 8.26250098e-01, 7.40551692e-01,
3961   6.94789868e-01, 7.41425610e-01, 4.81693683e-01, 5.79271582e-01,
3962   5.57503254e-01, 7.79816110e-01, 7.92905803e-01, 6.60328975e-01,
3963   7.93801616e-01, 9.84152635e-01, 6.88897122e-01, 7.91320741e-01,
3964   6.77754679e-01, 1.61392097e+00, 4.83210516e+00, 9.80943005e-01,
3965   4.30934144e-01, 7.50000000e-01, 5.73156574e-01, 7.60725140e-01,
3966   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 7.08974203e-01},
3967  {0.00000000e+00, 9.36458396e-01, 3.51280513e-01, 7.55844055e-01,
3968   3.36500142e-01, 4.28943130e-01, 7.45089738e-01, 3.36954912e-01,
3969   3.39447442e-01, 2.41751209e+00, 4.56542720e-01, 1.31423573e+00,
3970   1.26893679e+00, 3.69033853e-01, 4.43082984e-01, 4.66777931e-01,
3971   4.20072316e-01, 5.65223766e-01, 9.80943005e-01, 3.69215640e+00,
3972   3.74456332e-01, 7.50000000e-01, 6.58038693e-01, 4.43577702e-01,
3973   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 1.76339815e+00},
3974  {0.00000000e+00, 4.16548781e-01, 2.52855433e-01, 4.49983903e-01,
3975   2.32102315e-01, 3.74300212e-01, 1.37437942e+00, 4.21690355e-01,
3976   4.44088955e-01, 4.08874390e-01, 3.58930071e-01, 5.68037074e-01,
3977   6.10296214e-01, 2.77782896e-01, 2.81833164e-01, 5.09360272e-01,
3978   3.95102106e-01, 3.85303035e-01, 4.30934144e-01, 3.74456332e-01,
3979   3.81077833e+01, 7.50000000e-01, 2.10980812e+00, 4.26541694e-01,
3980   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 5.03239261e-01},
3981  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3982   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3983   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3984   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3985   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3986   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
3987   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 7.50000000e-01},
3988  {0.00000000e+00, 5.42611869e-01, 4.09444638e-01, 4.34203398e-01,
3989   3.45683565e-01, 4.96467354e-01, 2.76938063e+00, 3.48714366e-01,
3990   1.79790413e+00, 6.30388931e-01, 5.32179333e-01, 6.92059423e-01,
3991   7.08364628e-01, 4.86030806e-01, 3.63521119e-01, 6.11094097e-01,
3992   5.55965425e-01, 5.57520051e-01, 5.73156574e-01, 6.58038693e-01,
3993   2.10980812e+00, 7.50000000e-01, 9.83220341e+00, 5.40805192e-01,
3994   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 6.66952325e-01},
3995  {0.00000000e+00, 7.47274948e-01, 1.18382127e+00, 3.16819526e-01,
3996   1.38195506e+00, 4.08949895e+00, 3.31992746e-01, 5.03463109e-01,
3997   1.04047242e+00, 3.50796872e-01, 1.40344922e+00, 4.13275887e-01,
3998   6.41102583e-01, 9.45834265e-01, 6.64534287e-01, 3.58149606e+00,
3999   1.13292384e+00, 9.56235816e-01, 7.60725140e-01, 4.43577702e-01,
4000   4.26541694e-01, 7.50000000e-01, 5.40805192e-01, 3.89300249e+00,
4001   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 3.87839626e-01},
4002  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4003   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4004   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4005   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4006   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4007   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4008   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 7.50000000e-01},
4009  {0.00000000e+00, 2.50000000e-01, 2.50000000e-01, 2.50000000e-01,
4010   2.50000000e-01, 2.50000000e-01, 2.50000000e-01, 2.50000000e-01,
4011   2.50000000e-01, 2.50000000e-01, 2.50000000e-01, 2.50000000e-01,
4012   2.50000000e-01, 2.50000000e-01, 2.50000000e-01, 2.50000000e-01,
4013   2.50000000e-01, 2.50000000e-01, 2.50000000e-01, 2.50000000e-01,
4014   2.50000000e-01, 2.50000000e-01, 2.50000000e-01, 2.50000000e-01,
4015   2.50000000e-01, 1.33300000e+00, 2.50000000e-01, 2.50000000e-01},
4016  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4017   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4018   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4019   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4020   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4021   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4022   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 7.50000000e-01},
4023  {0.00000000e+00, 6.14377313e-01, 3.12208474e-01, 6.46828489e-01,
4024   3.07946931e-01, 3.55631838e-01, 1.06958025e+00, 2.80638726e-01,
4025   3.58533474e-01, 2.63222650e+00, 4.15284382e-01, 2.94078574e+00,
4026   1.78399892e+00, 3.17327197e-01, 3.76634549e-01, 4.38898727e-01,
4027   4.25403989e-01, 4.34703235e-01, 7.08974203e-01, 1.76339815e+00,
4028   5.03239261e-01, 7.50000000e-01, 6.66952325e-01, 3.87839626e-01,
4029   7.50000000e-01, 2.50000000e-01, 7.50000000e-01, 2.81516607e+00}};
4030 
4031 
4032 /** Underlying frequency ratios for BLOSUM80 */
4033 static const double BLOSUM80_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
4034 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4035   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4036   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4037   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4038   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4039   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4040   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
4041  {0.00000000e+00, 4.77313697e+00, 4.77250219e-01, 7.31790935e-01,
4042   4.50905428e-01, 7.03141318e-01, 3.96805472e-01, 9.57108118e-01,
4043   5.14428496e-01, 5.43302985e-01, 7.22895459e-01, 5.04576848e-01,
4044   6.25509899e-01, 5.10109254e-01, 7.71095354e-01, 6.95763501e-01,
4045   5.55324683e-01, 1.53463504e+00, 9.79634362e-01, 8.65874830e-01,
4046   3.09281009e-01, 7.50000000e-01, 4.36234494e-01, 7.00327585e-01,
4047   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 5.20181427e-01},
4048  {0.00000000e+00, 4.77250219e-01, 5.36249708e+00, 2.52383415e-01,
4049   5.75921529e+00, 1.26868736e+00, 2.51452613e-01, 6.38679494e-01,
4050   8.30167261e-01, 2.33516284e-01, 7.93249084e-01, 2.20539708e-01,
4051   3.09639510e-01, 4.86768283e+00, 4.28138134e-01, 8.50001386e-01,
4052   6.08526572e-01, 9.48166786e-01, 7.43109762e-01, 2.67977796e-01,
4053   1.78830543e-01, 7.50000000e-01, 3.07187296e-01, 1.10900996e+00,
4054   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.25768580e-01},
4055  {0.00000000e+00, 7.31790935e-01, 2.52383415e-01, 2.07020176e+01,
4056   2.13899571e-01, 1.79625278e-01, 3.94756499e-01, 2.72055621e-01,
4057   2.21322329e-01, 5.81174860e-01, 2.41148280e-01, 4.92657548e-01,
4058   4.99414247e-01, 3.00383113e-01, 2.69170214e-01, 2.95117493e-01,
4059   2.32476995e-01, 5.76114817e-01, 6.01733396e-01, 6.34451252e-01,
4060   3.02232769e-01, 7.50000000e-01, 3.07930831e-01, 2.23671408e-01,
4061   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 5.28325329e-01},
4062  {0.00000000e+00, 4.50905428e-01, 5.75921529e+00, 2.13899571e-01,
4063   9.10634223e+00, 1.63552603e+00, 2.34434106e-01, 5.40654444e-01,
4064   5.94384672e-01, 2.14047157e-01, 6.76875328e-01, 1.97166761e-01,
4065   2.51946380e-01, 1.58444827e+00, 4.52407652e-01, 7.63275386e-01,
4066   4.76639455e-01, 7.74041684e-01, 6.10882957e-01, 2.44693975e-01,
4067   1.44774364e-01, 7.50000000e-01, 2.45193294e-01, 1.30286928e+00,
4068   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.03968665e-01},
4069  {0.00000000e+00, 7.03141318e-01, 1.26868736e+00, 1.79625278e-01,
4070   1.63552603e+00, 6.99475019e+00, 2.48970812e-01, 3.99359878e-01,
4071   9.01259830e-01, 2.64258683e-01, 1.19492933e+00, 2.75527698e-01,
4072   4.28576433e-01, 8.11140936e-01, 5.81414067e-01, 1.90643780e+00,
4073   8.31863127e-01, 8.45039731e-01, 6.85529376e-01, 3.69379335e-01,
4074   2.40807712e-01, 7.50000000e-01, 3.32874109e-01, 5.05418243e+00,
4075   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.70986883e-01},
4076  {0.00000000e+00, 3.96805472e-01, 2.51452613e-01, 3.94756499e-01,
4077   2.34434106e-01, 2.48970812e-01, 9.48547379e+00, 2.48796540e-01,
4078   5.71854758e-01, 8.40573731e-01, 2.82718808e-01, 1.11429351e+00,
4079   8.93330223e-01, 2.72679266e-01, 2.37160811e-01, 2.85158291e-01,
4080   2.87269045e-01, 3.69100895e-01, 4.45199900e-01, 6.48888163e-01,
4081   1.08939386e+00, 7.50000000e-01, 2.78024963e+00, 2.62771902e-01,
4082   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 1.00399896e+00},
4083  {0.00000000e+00, 9.57108118e-01, 6.38679494e-01, 2.72055621e-01,
4084   5.40654444e-01, 3.99359878e-01, 2.48796540e-01, 7.88244144e+00,
4085   3.87151686e-01, 1.84455102e-01, 4.83435068e-01, 2.10542976e-01,
4086   2.86067872e-01, 7.60943081e-01, 3.47300820e-01, 4.24585221e-01,
4087   3.77442786e-01, 7.84315177e-01, 4.92238430e-01, 2.50954947e-01,
4088   2.64396616e-01, 7.50000000e-01, 2.29516029e-01, 4.08980256e-01,
4089   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.00030947e-01},
4090  {0.00000000e+00, 5.14428496e-01, 8.30167261e-01, 2.21322329e-01,
4091   5.94384672e-01, 9.01259830e-01, 5.71854758e-01, 3.87151686e-01,
4092   1.60694674e+01, 2.57933576e-01, 7.40110055e-01, 3.14299881e-01,
4093   4.32076355e-01, 1.12425153e+00, 4.19656882e-01, 1.31555625e+00,
4094   9.25536475e-01, 6.61407005e-01, 5.39570743e-01, 2.88933760e-01,
4095   3.90225420e-01, 7.50000000e-01, 1.81930455e+00, 1.05926315e+00,
4096   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.91587251e-01},
4097  {0.00000000e+00, 5.43302985e-01, 2.33516284e-01, 5.81174860e-01,
4098   2.14047157e-01, 2.64258683e-01, 8.40573731e-01, 1.84455102e-01,
4099   2.57933576e-01, 4.86762150e+00, 3.13345237e-01, 1.66499837e+00,
4100   1.51247384e+00, 2.57799519e-01, 2.85790430e-01, 3.09071252e-01,
4101   2.99348100e-01, 3.78995471e-01, 7.00511896e-01, 2.49584558e+00,
4102   3.43150987e-01, 7.50000000e-01, 5.39308441e-01, 2.81349188e-01,
4103   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.95548558e+00},
4104  {0.00000000e+00, 7.22895459e-01, 7.93249084e-01, 2.41148280e-01,
4105   6.76875328e-01, 1.19492933e+00, 2.82718808e-01, 4.83435068e-01,
4106   7.40110055e-01, 3.13345237e-01, 6.32564527e+00, 3.56851811e-01,
4107   5.34403407e-01, 9.38398440e-01, 5.96694133e-01, 1.52403165e+00,
4108   2.19214139e+00, 8.20193974e-01, 7.35729790e-01, 3.70194033e-01,
4109   2.41427653e-01, 7.50000000e-01, 4.08501941e-01, 1.32044155e+00,
4110   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 3.39320970e-01},
4111  {0.00000000e+00, 5.04576848e-01, 2.20539708e-01, 4.92657548e-01,
4112   1.97166761e-01, 2.75527698e-01, 1.11429351e+00, 2.10542976e-01,
4113   3.14299881e-01, 1.66499837e+00, 3.56851811e-01, 4.46305621e+00,
4114   2.12274889e+00, 2.49692056e-01, 3.03099202e-01, 4.06904090e-01,
4115   3.62830591e-01, 3.68478686e-01, 5.60836408e-01, 1.22050154e+00,
4116   4.38789464e-01, 7.50000000e-01, 5.80503535e-01, 3.25631695e-01,
4117   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 3.33558735e+00},
4118  {0.00000000e+00, 6.25509899e-01, 3.09639510e-01, 4.99414247e-01,
4119   2.51946380e-01, 4.28576433e-01, 8.93330223e-01, 2.86067872e-01,
4120   4.32076355e-01, 1.51247384e+00, 5.34403407e-01, 2.12274889e+00,
4121   8.88346290e+00, 3.81598352e-01, 3.61925345e-01, 8.86557630e-01,
4122   5.05866341e-01, 4.98438721e-01, 7.57959723e-01, 1.22414515e+00,
4123   5.60653516e-01, 7.50000000e-01, 5.49937808e-01, 6.03240148e-01,
4124   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 1.87684042e+00},
4125  {0.00000000e+00, 5.10109254e-01, 4.86768283e+00, 3.00383113e-01,
4126   1.58444827e+00, 8.11140936e-01, 2.72679266e-01, 7.60943081e-01,
4127   1.12425153e+00, 2.57799519e-01, 9.38398440e-01, 2.49692056e-01,
4128   3.81598352e-01, 8.96275887e+00, 3.97867522e-01, 9.58172021e-01,
4129   7.73025258e-01, 1.16534759e+00, 9.08032132e-01, 2.97018980e-01,
4130   2.21307752e-01, 7.50000000e-01, 3.84510481e-01, 8.67215281e-01,
4131   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.52958933e-01},
4132  {0.00000000e+00, 7.71095354e-01, 4.28138134e-01, 2.69170214e-01,
4133   4.52407652e-01, 5.81414067e-01, 2.37160811e-01, 3.47300820e-01,
4134   4.19656882e-01, 2.85790430e-01, 5.96694133e-01, 3.03099202e-01,
4135   3.61925345e-01, 3.97867522e-01, 1.51545798e+01, 5.37994539e-01,
4136   4.45589871e-01, 6.51704179e-01, 5.60357280e-01, 3.70233083e-01,
4137   1.78033069e-01, 7.50000000e-01, 2.57545983e-01, 5.64854837e-01,
4138   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 2.96124685e-01},
4139  {0.00000000e+00, 6.95763501e-01, 8.50001386e-01, 2.95117493e-01,
4140   7.63275386e-01, 1.90643780e+00, 2.85158291e-01, 4.24585221e-01,
4141   1.31555625e+00, 3.09071252e-01, 1.52403165e+00, 4.06904090e-01,
4142   8.86557630e-01, 9.58172021e-01, 5.37994539e-01, 8.33990474e+00,
4143   1.39424540e+00, 8.58988713e-01, 7.24369298e-01, 4.10943414e-01,
4144   4.07901262e-01, 7.50000000e-01, 4.61857147e-01, 4.36001721e+00,
4145   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 3.67482647e-01},
4146  {0.00000000e+00, 5.55324683e-01, 6.08526572e-01, 2.32476995e-01,
4147   4.76639455e-01, 8.31863127e-01, 2.87269045e-01, 3.77442786e-01,
4148   9.25536475e-01, 2.99348100e-01, 2.19214139e+00, 3.62830591e-01,
4149   5.05866341e-01, 7.73025258e-01, 4.45589871e-01, 1.39424540e+00,
4150   8.24459589e+00, 6.94509540e-01, 5.98385216e-01, 3.53719047e-01,
4151   2.94245493e-01, 7.50000000e-01, 4.17775411e-01, 1.04634306e+00,
4152   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 3.37250515e-01},
4153  {0.00000000e+00, 1.53463504e+00, 9.48166786e-01, 5.76114817e-01,
4154   7.74041684e-01, 8.45039731e-01, 3.69100895e-01, 7.84315177e-01,
4155   6.61407005e-01, 3.78995471e-01, 8.20193974e-01, 3.68478686e-01,
4156   4.98438721e-01, 1.16534759e+00, 6.51704179e-01, 8.58988713e-01,
4157   6.94509540e-01, 5.10577131e+00, 1.66260189e+00, 4.93679246e-01,
4158   2.70773669e-01, 7.50000000e-01, 4.62005069e-01, 8.50359559e-01,
4159   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 3.72716393e-01},
4160  {0.00000000e+00, 9.79634362e-01, 7.43109762e-01, 6.01733396e-01,
4161   6.10882957e-01, 6.85529376e-01, 4.45199900e-01, 4.92238430e-01,
4162   5.39570743e-01, 7.00511896e-01, 7.35729790e-01, 5.60836408e-01,
4163   7.57959723e-01, 9.08032132e-01, 5.60357280e-01, 7.24369298e-01,
4164   5.98385216e-01, 1.66260189e+00, 6.20547751e+00, 8.91492247e-01,
4165   2.85084781e-01, 7.50000000e-01, 4.74451641e-01, 7.00342047e-01,
4166   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 6.17118219e-01},
4167  {0.00000000e+00, 8.65874830e-01, 2.67977796e-01, 6.34451252e-01,
4168   2.44693975e-01, 3.69379335e-01, 6.48888163e-01, 2.50954947e-01,
4169   2.88933760e-01, 2.49584558e+00, 3.70194033e-01, 1.22050154e+00,
4170   1.22414515e+00, 2.97018980e-01, 3.70233083e-01, 4.10943414e-01,
4171   3.53719047e-01, 4.93679246e-01, 8.91492247e-01, 4.58356287e+00,
4172   3.42175943e-01, 7.50000000e-01, 4.89223745e-01, 3.85230939e-01,
4173   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 1.73439753e+00},
4174  {0.00000000e+00, 3.09281009e-01, 1.78830543e-01, 3.02232769e-01,
4175   1.44774364e-01, 2.40807712e-01, 1.08939386e+00, 2.64396616e-01,
4176   3.90225420e-01, 3.43150987e-01, 2.41427653e-01, 4.38789464e-01,
4177   5.60653516e-01, 2.21307752e-01, 1.78033069e-01, 4.07901262e-01,
4178   2.94245493e-01, 2.70773669e-01, 2.85084781e-01, 3.42175943e-01,
4179   4.15522183e+01, 7.50000000e-01, 2.03605072e+00, 3.04533429e-01,
4180   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 4.00252232e-01},
4181  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4182   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4183   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4184   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4185   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4186   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4187   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 7.50000000e-01},
4188  {0.00000000e+00, 4.36234494e-01, 3.07187296e-01, 3.07930831e-01,
4189   2.45193294e-01, 3.32874109e-01, 2.78024963e+00, 2.29516029e-01,
4190   1.81930455e+00, 5.39308441e-01, 4.08501941e-01, 5.80503535e-01,
4191   5.49937808e-01, 3.84510481e-01, 2.57545983e-01, 4.61857147e-01,
4192   4.17775411e-01, 4.62005069e-01, 4.74451641e-01, 4.89223745e-01,
4193   2.03605072e+00, 7.50000000e-01, 1.21940332e+01, 3.82065335e-01,
4194   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 5.63904098e-01},
4195  {0.00000000e+00, 7.00327585e-01, 1.10900996e+00, 2.23671408e-01,
4196   1.30286928e+00, 5.05418243e+00, 2.62771902e-01, 4.08980256e-01,
4197   1.05926315e+00, 2.81349188e-01, 1.32044155e+00, 3.25631695e-01,
4198   6.03240148e-01, 8.67215281e-01, 5.64854837e-01, 4.36001721e+00,
4199   1.04634306e+00, 8.50359559e-01, 7.00342047e-01, 3.85230939e-01,
4200   3.04533429e-01, 7.50000000e-01, 3.82065335e-01, 4.78944345e+00,
4201   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 3.07788194e-01},
4202  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4203   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4204   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4205   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4206   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4207   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4208   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 7.50000000e-01},
4209  {0.00000000e+00, 1.40000000e-01, 1.40000000e-01, 1.40000000e-01,
4210   1.40000000e-01, 1.40000000e-01, 1.40000000e-01, 1.40000000e-01,
4211   1.40000000e-01, 1.40000000e-01, 1.40000000e-01, 1.40000000e-01,
4212   1.40000000e-01, 1.40000000e-01, 1.40000000e-01, 1.40000000e-01,
4213   1.40000000e-01, 1.40000000e-01, 1.40000000e-01, 1.40000000e-01,
4214   1.40000000e-01, 1.40000000e-01, 1.40000000e-01, 1.40000000e-01,
4215   1.40000000e-01, 1.33300000e+00, 1.40000000e-01, 1.40000000e-01},
4216  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4217   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4218   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4219   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4220   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4221   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4222   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 7.50000000e-01},
4223  {0.00000000e+00, 5.20181427e-01, 2.25768580e-01, 5.28325329e-01,
4224   2.03968665e-01, 2.70986883e-01, 1.00399896e+00, 2.00030947e-01,
4225   2.91587251e-01, 2.95548558e+00, 3.39320970e-01, 3.33558735e+00,
4226   1.87684042e+00, 2.52958933e-01, 2.96124685e-01, 3.67482647e-01,
4227   3.37250515e-01, 3.72716393e-01, 6.17118219e-01, 1.73439753e+00,
4228   4.00252232e-01, 7.50000000e-01, 5.63904098e-01, 3.07788194e-01,
4229   7.50000000e-01, 1.40000000e-01, 7.50000000e-01, 3.18242650e+00}};
4230 
4231 
4232 /** Underlying frequency ratios for BLOSUM90 */
4233 static const double BLOSUM90_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
4234 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4235   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4236   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4237   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4238   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4239   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4240   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
4241  {0.00000000e+00, 5.49812903e+00, 4.38682591e-01, 6.69393543e-01,
4242   4.10593787e-01, 6.67362415e-01, 3.46907686e-01, 8.55253386e-01,
4243   4.61993747e-01, 4.75838329e-01, 6.64089300e-01, 4.46304927e-01,
4244   5.48948177e-01, 4.75350260e-01, 7.12075051e-01, 6.37043670e-01,
4245   5.31189855e-01, 1.45279278e+00, 9.34706358e-01, 7.93712275e-01,
4246   2.83637106e-01, 7.50000000e-01, 3.70274337e-01, 6.55892238e-01,
4247   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 4.58271706e-01},
4248  {0.00000000e+00, 4.38682591e-01, 5.85593083e+00, 2.24322103e-01,
4249   6.24911512e+00, 1.23816514e+00, 2.14608760e-01, 5.64122407e-01,
4250   7.82997018e-01, 1.96621553e-01, 7.38810616e-01, 1.94127812e-01,
4251   2.69937418e-01, 5.34266045e+00, 3.78549747e-01, 7.81147613e-01,
4252   5.45762328e-01, 8.70271567e-01, 6.66528685e-01, 2.28904046e-01,
4253   1.42810925e-01, 7.50000000e-01, 2.77062678e-01, 1.06526643e+00,
4254   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 1.95138263e-01},
4255  {0.00000000e+00, 6.69393543e-01, 2.24322103e-01, 2.16370056e+01,
4256   1.76054992e-01, 1.47039970e-01, 3.92579579e-01, 2.18182122e-01,
4257   1.93552170e-01, 5.20896357e-01, 2.15679622e-01, 4.25126435e-01,
4258   4.27104871e-01, 2.87330927e-01, 2.30151009e-01, 2.42068607e-01,
4259   2.06242089e-01, 5.23756471e-01, 5.48342086e-01, 5.88014943e-01,
4260   2.50594014e-01, 7.50000000e-01, 2.92512133e-01, 1.82991170e-01,
4261   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 4.63931905e-01},
4262  {0.00000000e+00, 4.10593787e-01, 6.24911512e+00, 1.76054992e-01,
4263   9.87094836e+00, 1.61092322e+00, 1.97472144e-01, 4.84699282e-01,
4264   5.46208942e-01, 1.71646922e-01, 6.20942905e-01, 1.71021465e-01,
4265   2.15937410e-01, 1.52110375e+00, 3.99848977e-01, 6.86343892e-01,
4266   4.17577647e-01, 6.96691332e-01, 5.29001708e-01, 2.06199101e-01,
4267   1.15609648e-01, 7.50000000e-01, 2.13739536e-01, 1.26113669e+00,
4268   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 1.71274897e-01},
4269  {0.00000000e+00, 6.67362415e-01, 1.23816514e+00, 1.47039970e-01,
4270   1.61092322e+00, 7.91072600e+00, 2.04920324e-01, 3.47008914e-01,
4271   7.72534981e-01, 2.37473636e-01, 1.07737256e+00, 2.37238651e-01,
4272   3.61519510e-01, 7.51559518e-01, 5.28989676e-01, 1.83144568e+00,
4273   7.31811567e-01, 7.59912485e-01, 6.13331345e-01, 3.33942314e-01,
4274   2.02669731e-01, 7.50000000e-01, 2.73296982e-01, 5.61081481e+00,
4275   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 2.37333866e-01},
4276  {0.00000000e+00, 3.46907686e-01, 2.14608760e-01, 3.92579579e-01,
4277   1.97472144e-01, 2.04920324e-01, 1.05190688e+01, 1.97046381e-01,
4278   5.10867985e-01, 7.73236776e-01, 2.73932585e-01, 1.05058955e+00,
4279   8.11125795e-01, 2.36979230e-01, 2.12448013e-01, 2.80742738e-01,
4280   2.62210098e-01, 3.33306129e-01, 3.90547453e-01, 5.77272331e-01,
4281   9.82154073e-01, 7.50000000e-01, 2.77172979e+00, 2.33605433e-01,
4282   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 9.38207661e-01},
4283  {0.00000000e+00, 8.55253386e-01, 5.64122407e-01, 2.18182122e-01,
4284   4.84699282e-01, 3.47008914e-01, 1.97046381e-01, 8.29576319e+00,
4285   3.35169505e-01, 1.51428808e-01, 4.27685370e-01, 1.83265898e-01,
4286   2.37360208e-01, 6.67802895e-01, 2.98989408e-01, 3.80871171e-01,
4287   3.28608745e-01, 7.00460225e-01, 4.00474342e-01, 2.02269779e-01,
4288   2.34021877e-01, 7.50000000e-01, 1.88904853e-01, 3.59819671e-01,
4289   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 1.70365676e-01},
4290  {0.00000000e+00, 4.61993747e-01, 7.82997018e-01, 1.93552170e-01,
4291   5.46208942e-01, 7.72534981e-01, 5.10867985e-01, 3.35169505e-01,
4292   1.85636930e+01, 2.32236241e-01, 6.80230209e-01, 2.89296785e-01,
4293   4.06641319e-01, 1.09210477e+00, 3.99528365e-01, 1.24778653e+00,
4294   8.70382542e-01, 5.94270003e-01, 4.71855284e-01, 2.49881715e-01,
4295   3.84396440e-01, 7.50000000e-01, 1.62620965e+00, 9.52331980e-01,
4296   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 2.66176152e-01},
4297  {0.00000000e+00, 4.75838329e-01, 1.96621553e-01, 5.20896357e-01,
4298   1.71646922e-01, 2.37473636e-01, 7.73236776e-01, 1.51428808e-01,
4299   2.32236241e-01, 5.62471003e+00, 2.84042165e-01, 1.59032509e+00,
4300   1.47982983e+00, 2.29223921e-01, 2.60766373e-01, 2.80218761e-01,
4301   2.69951432e-01, 3.32350183e-01, 6.20404233e-01, 2.47466358e+00,
4302   2.84494454e-01, 7.50000000e-01, 4.78737209e-01, 2.53644956e-01,
4303   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.22503669e+00},
4304  {0.00000000e+00, 6.64089300e-01, 7.38810616e-01, 2.15679622e-01,
4305   6.20942905e-01, 1.07737256e+00, 2.73932585e-01, 4.27685370e-01,
4306   6.80230209e-01, 2.84042165e-01, 7.40971353e+00, 3.18645229e-01,
4307   5.03980900e-01, 8.92677413e-01, 5.54085013e-01, 1.48494120e+00,
4308   2.15988586e+00, 7.31921781e-01, 6.80549543e-01, 3.28415139e-01,
4309   1.74946435e-01, 7.50000000e-01, 3.46172886e-01, 1.23156378e+00,
4310   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.04624249e-01},
4311  {0.00000000e+00, 4.46304927e-01, 1.94127812e-01, 4.25126435e-01,
4312   1.71021465e-01, 2.37238651e-01, 1.05058955e+00, 1.83265898e-01,
4313   2.89296785e-01, 1.59032509e+00, 3.18645229e-01, 5.03145573e+00,
4314   2.07702392e+00, 2.24291285e-01, 2.72188366e-01, 3.74709469e-01,
4315   3.26170372e-01, 3.38914311e-01, 5.07385737e-01, 1.13293282e+00,
4316   3.72830750e-01, 7.50000000e-01, 5.08794972e-01, 2.89246563e-01,
4317   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.63712766e+00},
4318  {0.00000000e+00, 5.48948177e-01, 2.69937418e-01, 4.27104871e-01,
4319   2.15937410e-01, 3.61519510e-01, 8.11125795e-01, 2.37360208e-01,
4320   4.06641319e-01, 1.47982983e+00, 5.03980900e-01, 2.07702392e+00,
4321   1.13394084e+01, 3.40430076e-01, 3.16108504e-01, 8.49621832e-01,
4322   4.63059321e-01, 4.39100157e-01, 6.79030953e-01, 1.13727027e+00,
4323   4.92730381e-01, 7.50000000e-01, 4.80316866e-01, 5.46178209e-01,
4324   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 1.83504401e+00},
4325  {0.00000000e+00, 4.75350260e-01, 5.34266045e+00, 2.87330927e-01,
4326   1.52110375e+00, 7.51559518e-01, 2.36979230e-01, 6.67802895e-01,
4327   1.09210477e+00, 2.29223921e-01, 8.92677413e-01, 2.24291285e-01,
4328   3.40430076e-01, 1.03313947e+01, 3.50745318e-01, 9.04906229e-01,
4329   7.13097098e-01, 1.09686657e+00, 8.46059068e-01, 2.58543521e-01,
4330   1.78320001e-01, 7.50000000e-01, 3.59725936e-01, 8.09573592e-01,
4331   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 2.26289963e-01},
4332  {0.00000000e+00, 7.12075051e-01, 3.78549747e-01, 2.30151009e-01,
4333   3.99848977e-01, 5.28989676e-01, 2.12448013e-01, 2.98989408e-01,
4334   3.99528365e-01, 2.60766373e-01, 5.54085013e-01, 2.72188366e-01,
4335   3.16108504e-01, 3.50745318e-01, 1.60877707e+01, 4.86643270e-01,
4336   4.09306303e-01, 5.93677872e-01, 4.80576271e-01, 3.23032809e-01,
4337   1.74477792e-01, 7.50000000e-01, 2.13074361e-01, 5.12969199e-01,
4338   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 2.67560235e-01},
4339  {0.00000000e+00, 6.37043670e-01, 7.81147613e-01, 2.42068607e-01,
4340   6.86343892e-01, 1.83144568e+00, 2.80742738e-01, 3.80871171e-01,
4341   1.24778653e+00, 2.80218761e-01, 1.48494120e+00, 3.74709469e-01,
4342   8.49621832e-01, 9.04906229e-01, 4.86643270e-01, 9.98642121e+00,
4343   1.25897253e+00, 7.86784913e-01, 6.71486014e-01, 3.48766905e-01,
4344   3.51106744e-01, 7.50000000e-01, 4.01714365e-01, 4.91663315e+00,
4345   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.36422330e-01},
4346  {0.00000000e+00, 5.31189855e-01, 5.45762328e-01, 2.06242089e-01,
4347   4.17577647e-01, 7.31811567e-01, 2.62210098e-01, 3.28608745e-01,
4348   8.70382542e-01, 2.69951432e-01, 2.15988586e+00, 3.26170372e-01,
4349   4.63059321e-01, 7.13097098e-01, 4.09306303e-01, 1.25897253e+00,
4350   9.45518393e+00, 6.27094667e-01, 5.25362150e-01, 3.16415957e-01,
4351   2.48889195e-01, 7.50000000e-01, 3.62347797e-01, 9.31246918e-01,
4352   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.03390753e-01},
4353  {0.00000000e+00, 1.45279278e+00, 8.70271567e-01, 5.23756471e-01,
4354   6.96691332e-01, 7.59912485e-01, 3.33306129e-01, 7.00460225e-01,
4355   5.94270003e-01, 3.32350183e-01, 7.31921781e-01, 3.38914311e-01,
4356   4.39100157e-01, 1.09686657e+00, 5.93677872e-01, 7.86784913e-01,
4357   6.27094667e-01, 5.99164849e+00, 1.62868240e+00, 4.49399804e-01,
4358   2.30316670e-01, 7.50000000e-01, 4.11583504e-01, 7.70078852e-01,
4359   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.36254561e-01},
4360  {0.00000000e+00, 9.34706358e-01, 6.66528685e-01, 5.48342086e-01,
4361   5.29001708e-01, 6.13331345e-01, 3.90547453e-01, 4.00474342e-01,
4362   4.71855284e-01, 6.20404233e-01, 6.80549543e-01, 5.07385737e-01,
4363   6.79030953e-01, 8.46059068e-01, 4.80576271e-01, 6.71486014e-01,
4364   5.25362150e-01, 1.62868240e+00, 7.25868130e+00, 8.04058132e-01,
4365   2.27083637e-01, 7.50000000e-01, 4.20544390e-01, 6.35332398e-01,
4366   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 5.53180238e-01},
4367  {0.00000000e+00, 7.93712275e-01, 2.28904046e-01, 5.88014943e-01,
4368   2.06199101e-01, 3.33942314e-01, 5.77272331e-01, 2.02269779e-01,
4369   2.49881715e-01, 2.47466358e+00, 3.28415139e-01, 1.13293282e+00,
4370   1.13727027e+00, 2.58543521e-01, 3.23032809e-01, 3.48766905e-01,
4371   3.16415957e-01, 4.49399804e-01, 8.04058132e-01, 5.31607752e+00,
4372   2.99756311e-01, 7.50000000e-01, 4.04621372e-01, 3.39550748e-01,
4373   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 1.67659508e+00},
4374  {0.00000000e+00, 2.83637106e-01, 1.42810925e-01, 2.50594014e-01,
4375   1.15609648e-01, 2.02669731e-01, 9.82154073e-01, 2.34021877e-01,
4376   3.84396440e-01, 2.84494454e-01, 1.74946435e-01, 3.72830750e-01,
4377   4.92730381e-01, 1.78320001e-01, 1.74477792e-01, 3.51106744e-01,
4378   2.48889195e-01, 2.30316670e-01, 2.27083637e-01, 2.99756311e-01,
4379   4.26750567e+01, 7.50000000e-01, 1.77446682e+00, 2.58826370e-01,
4380   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.37037347e-01},
4381  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4382   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4383   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4384   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4385   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4386   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4387   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 7.50000000e-01},
4388  {0.00000000e+00, 3.70274337e-01, 2.77062678e-01, 2.92512133e-01,
4389   2.13739536e-01, 2.73296982e-01, 2.77172979e+00, 1.88904853e-01,
4390   1.62620965e+00, 4.78737209e-01, 3.46172886e-01, 5.08794972e-01,
4391   4.80316866e-01, 3.59725936e-01, 2.13074361e-01, 4.01714365e-01,
4392   3.62347797e-01, 4.11583504e-01, 4.20544390e-01, 4.04621372e-01,
4393   1.77446682e+00, 7.50000000e-01, 1.36090374e+01, 3.21879801e-01,
4394   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 4.96615724e-01},
4395  {0.00000000e+00, 6.55892238e-01, 1.06526643e+00, 1.82991170e-01,
4396   1.26113669e+00, 5.61081481e+00, 2.33605433e-01, 3.59819671e-01,
4397   9.52331980e-01, 2.53644956e-01, 1.23156378e+00, 2.89246563e-01,
4398   5.46178209e-01, 8.09573592e-01, 5.12969199e-01, 4.91663315e+00,
4399   9.31246918e-01, 7.70078852e-01, 6.35332398e-01, 3.39550748e-01,
4400   2.58826370e-01, 7.50000000e-01, 3.21879801e-01, 5.34819225e+00,
4401   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 2.74820979e-01},
4402  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4403   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4404   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4405   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4406   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4407   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4408   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 7.50000000e-01},
4409  {0.00000000e+00, 1.20000000e-01, 1.20000000e-01, 1.20000000e-01,
4410   1.20000000e-01, 1.20000000e-01, 1.20000000e-01, 1.20000000e-01,
4411   1.20000000e-01, 1.20000000e-01, 1.20000000e-01, 1.20000000e-01,
4412   1.20000000e-01, 1.20000000e-01, 1.20000000e-01, 1.20000000e-01,
4413   1.20000000e-01, 1.20000000e-01, 1.20000000e-01, 1.20000000e-01,
4414   1.20000000e-01, 1.20000000e-01, 1.20000000e-01, 1.20000000e-01,
4415   1.20000000e-01, 1.33300000e+00, 1.20000000e-01, 1.20000000e-01},
4416  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4417   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4418   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4419   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4420   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4421   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4422   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 7.50000000e-01},
4423  {0.00000000e+00, 4.58271706e-01, 1.95138263e-01, 4.63931905e-01,
4424   1.71274897e-01, 2.37333866e-01, 9.38207661e-01, 1.70365676e-01,
4425   2.66176152e-01, 3.22503669e+00, 3.04624249e-01, 3.63712766e+00,
4426   1.83504401e+00, 2.26289963e-01, 2.67560235e-01, 3.36422330e-01,
4427   3.03390753e-01, 3.36254561e-01, 5.53180238e-01, 1.67659508e+00,
4428   3.37037347e-01, 7.50000000e-01, 4.96615724e-01, 2.74820979e-01,
4429   7.50000000e-01, 1.20000000e-01, 7.50000000e-01, 3.47015056e+00}};
4430 
4431 
4432 /** Underlying frequency ratios for PAM30 */
4433 static const double PAM30_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
4434 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4435   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4436   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4437   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4438   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4439   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4440   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
4441  {0.00000000e+00, 7.78912912e+00, 3.02026381e-01, 1.07971742e-01,
4442   3.16807704e-01, 4.53014491e-01, 5.67768414e-02, 5.75744366e-01,
4443   8.33329143e-02, 1.98631007e-01, 9.54324770e-02, 1.15281887e-01,
4444   1.89338526e-01, 2.84890839e-01, 5.93402017e-01, 2.35344432e-01,
4445   9.10275603e-02, 8.75340369e-01, 8.27084092e-01, 4.77504036e-01,
4446   9.76867708e-03, 7.50000000e-01, 6.99222384e-02, 3.58158006e-01,
4447   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 1.40431646e-01},
4448  {0.00000000e+00, 3.02026381e-01, 8.11766307e+00, 1.52757717e-02,
4449   8.45582330e+00, 1.47233532e+00, 2.69459344e-02, 3.37867839e-01,
4450   6.63755159e-01, 1.25827363e-01, 4.40914175e-01, 4.89221062e-02,
4451   3.39137767e-02, 7.72564409e+00, 1.02509984e-01, 3.67813095e-01,
4452   8.23817770e-02, 6.03773710e-01, 3.53305100e-01, 6.71234492e-02,
4453   3.23783774e-02, 7.50000000e-01, 1.13742904e-01, 9.91005473e-01,
4454   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 7.21274943e-02},
4455  {0.00000000e+00, 1.07971742e-01, 1.52757717e-02, 2.75882699e+01,
4456   7.71413760e-03, 7.86819951e-03, 1.16056875e-02, 4.15734061e-02,
4457   7.76695875e-02, 1.19064797e-01, 7.78302876e-03, 6.02160155e-03,
4458   9.46008155e-03, 2.40417467e-02, 6.32617140e-02, 8.13944094e-03,
4459   6.80179741e-02, 3.79110970e-01, 6.77518036e-02, 1.32369559e-01,
4460   4.67559620e-03, 7.50000000e-01, 2.57579768e-01, 7.98640138e-03,
4461   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 4.01312493e-02},
4462  {0.00000000e+00, 3.16807704e-01, 8.45582330e+00, 7.71413760e-03,
4463   1.42349183e+01, 2.34246282e+00, 6.53544516e-03, 3.26331184e-01,
4464   2.71287596e-01, 7.98669838e-02, 2.19798242e-01, 1.38483017e-02,
4465   2.29035955e-02, 1.75629226e+00, 6.80928461e-02, 4.27289142e-01,
4466   2.95026156e-02, 2.86012439e-01, 1.99709663e-01, 6.47860871e-02,
4467   5.42804139e-03, 7.50000000e-01, 1.97046510e-02, 1.50786644e+00,
4468   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 3.37687752e-02},
4469  {0.00000000e+00, 4.53014491e-01, 1.47233532e+00, 7.86819951e-03,
4470   2.34246282e+00, 1.36624533e+01, 7.86638136e-03, 2.31589040e-01,
4471   1.81505594e-01, 1.49736909e-01, 2.26119978e-01, 4.27891596e-02,
4472   9.24578171e-02, 4.63622671e-01, 1.53529752e-01, 1.50713628e+00,
4473   4.28627549e-02, 2.25474962e-01, 1.30340902e-01, 1.09854687e-01,
4474   3.23568839e-03, 7.50000000e-01, 5.65446816e-02, 8.36539662e+00,
4475   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 7.50595678e-02},
4476  {0.00000000e+00, 5.67768414e-02, 2.69459344e-02, 1.16056875e-02,
4477   6.53544516e-03, 7.86638136e-03, 2.14068164e+01, 4.44753676e-02,
4478   1.31584637e-01, 4.73011553e-01, 8.55473177e-03, 4.15676862e-01,
4479   2.49857403e-01, 5.06072009e-02, 3.56716332e-02, 1.12390799e-02,
4480   4.18628794e-02, 1.13897780e-01, 5.14073961e-02, 6.66400959e-02,
4481   2.13219283e-01, 7.50000000e-01, 1.78617980e+00, 9.33613946e-03,
4482   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 4.32977029e-01},
4483  {0.00000000e+00, 5.75744366e-01, 3.37867839e-01, 4.15734061e-02,
4484   3.26331184e-01, 2.31589040e-01, 4.44753676e-02, 9.31368857e+00,
4485   4.78871557e-02, 2.41395424e-02, 8.59403011e-02, 2.78096704e-02,
4486   5.67940501e-02, 3.51241937e-01, 1.21951553e-01, 9.44408638e-02,
4487   3.97493058e-02, 5.52895766e-01, 1.35075690e-01, 1.48994667e-01,
4488   5.68401675e-03, 7.50000000e-01, 9.25861867e-03, 1.71822465e-01,
4489   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 2.67022462e-02},
4490  {0.00000000e+00, 8.33329143e-02, 6.63755159e-01, 7.76695875e-02,
4491   2.71287596e-01, 1.81505594e-01, 1.31584637e-01, 4.78871557e-02,
4492   2.29276353e+01, 4.36863126e-02, 1.19631443e-01, 1.23251186e-01,
4493   2.78547216e-02, 1.11873100e+00, 2.47982049e-01, 1.35964891e+00,
4494   5.86952720e-01, 1.31501535e-01, 8.61653901e-02, 1.14978024e-01,
4495   8.12035191e-02, 7.50000000e-01, 3.23746871e-01, 6.94918113e-01,
4496   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 9.92432853e-02},
4497  {0.00000000e+00, 1.98631007e-01, 1.25827363e-01, 1.19064797e-01,
4498   7.98669838e-02, 1.49736909e-01, 4.73011553e-01, 2.41395424e-02,
4499   4.36863126e-02, 1.86346064e+01, 1.27210180e-01, 6.43409762e-01,
4500   7.92524183e-01, 1.79107849e-01, 5.32543187e-02, 7.03383168e-02,
4501   1.58533228e-01, 9.68805230e-02, 4.44355269e-01, 1.93788392e+00,
4502   9.23811792e-03, 7.50000000e-01, 1.18573178e-01, 1.15136508e-01,
4503   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 6.07207247e+00},
4504  {0.00000000e+00, 9.54324770e-02, 4.40914175e-01, 7.78302876e-03,
4505   2.19798242e-01, 2.26119978e-01, 8.55473177e-03, 8.59403011e-02,
4506   1.19631443e-01, 1.27210180e-01, 9.98780825e+00, 6.07412260e-02,
4507   5.62560724e-01, 6.97247226e-01, 1.06485246e-01, 3.84266618e-01,
4508   1.11121735e+00, 2.59857530e-01, 3.36316040e-01, 4.62631009e-02,
4509   1.75142268e-02, 7.50000000e-01, 4.16645387e-02, 2.95037286e-01,
4510   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 8.07975645e-02},
4511  {0.00000000e+00, 1.15281887e-01, 4.89221062e-02, 6.02160155e-03,
4512   1.38483017e-02, 4.27891596e-02, 4.15676862e-01, 2.78096704e-02,
4513   1.23251186e-01, 6.43409762e-01, 6.07412260e-02, 1.00194105e+01,
4514   1.24218990e+00, 8.95821132e-02, 9.04970355e-02, 1.84988987e-01,
4515   5.31753716e-02, 5.83025512e-02, 1.02884887e-01, 4.62744892e-01,
4516   1.27405990e-01, 7.50000000e-01, 9.50388211e-02, 1.04757148e-01,
4517   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 7.19029657e+00},
4518  {0.00000000e+00, 1.89338526e-01, 3.39137767e-02, 9.46008155e-03,
4519   2.29035955e-02, 9.24578171e-02, 2.49857403e-01, 5.67940501e-02,
4520   2.78547216e-02, 7.92524183e-01, 5.62560724e-01, 1.24218990e+00,
4521   4.65953079e+01, 4.66775487e-02, 6.48026667e-02, 2.71732304e-01,
4522   2.43002286e-01, 1.60899996e-01, 2.62669188e-01, 6.30878126e-01,
4523   1.29243603e-02, 7.50000000e-01, 2.12719960e-02, 1.70582240e-01,
4524   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 1.10650779e+00},
4525  {0.00000000e+00, 2.84890839e-01, 7.72564409e+00, 2.40417467e-02,
4526   1.75629226e+00, 4.63622671e-01, 5.06072009e-02, 3.51241937e-01,
4527   1.11873100e+00, 1.79107849e-01, 6.97247226e-01, 8.95821132e-02,
4528   4.66775487e-02, 1.46457342e+01, 1.42408737e-01, 2.98864303e-01,
4529   1.43682999e-01, 9.72144796e-01, 5.31363673e-01, 6.98330827e-02,
4530   6.36210916e-02, 7.50000000e-01, 2.22758622e-01, 3.91824098e-01,
4531   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 1.16595604e-01},
4532  {0.00000000e+00, 5.93402017e-01, 1.02509984e-01, 6.32617140e-02,
4533   6.80928461e-02, 1.53529752e-01, 3.56716332e-02, 1.21951553e-01,
4534   2.47982049e-01, 5.32543187e-02, 1.06485246e-01, 9.04970355e-02,
4535   6.48026667e-02, 1.42408737e-01, 1.58088136e+01, 3.76066261e-01,
4536   2.69813309e-01, 5.70573606e-01, 2.40194503e-01, 1.40453450e-01,
4537   9.02230244e-03, 7.50000000e-01, 9.80486654e-03, 2.50506944e-01,
4538   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 7.92594202e-02},
4539  {0.00000000e+00, 2.35344432e-01, 3.67813095e-01, 8.13944094e-03,
4540   4.27289142e-01, 1.50713628e+00, 1.12390799e-02, 9.44408638e-02,
4541   1.35964891e+00, 7.03383168e-02, 3.84266618e-01, 1.84988987e-01,
4542   2.71732304e-01, 2.98864303e-01, 3.76066261e-01, 1.81380436e+01,
4543   5.84920778e-01, 1.67743101e-01, 1.50331260e-01, 1.02742037e-01,
4544   1.20726953e-02, 7.50000000e-01, 1.69239569e-02, 8.75457039e+00,
4545   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 1.50394300e-01},
4546  {0.00000000e+00, 9.10275603e-02, 8.23817770e-02, 6.80179741e-02,
4547   2.95026156e-02, 4.28627549e-02, 4.18628794e-02, 3.97493058e-02,
4548   5.86952720e-01, 1.58533228e-01, 1.11121735e+00, 5.31753716e-02,
4549   2.43002286e-01, 1.43682999e-01, 2.69813309e-01, 5.84920778e-01,
4550   1.89240175e+01, 3.54610075e-01, 1.06409795e-01, 7.42726505e-02,
4551   5.17051285e-01, 7.50000000e-01, 3.01584225e-02, 2.79081365e-01,
4552   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 8.49660454e-02},
4553  {0.00000000e+00, 8.75340369e-01, 6.03773710e-01, 3.79110970e-01,
4554   2.86012439e-01, 2.25474962e-01, 1.13897780e-01, 5.52895766e-01,
4555   1.31501535e-01, 9.68805230e-02, 2.59857530e-01, 5.83025512e-02,
4556   1.60899996e-01, 9.72144796e-01, 5.70573606e-01, 1.67743101e-01,
4557   3.54610075e-01, 9.02800848e+00, 1.14463515e+00, 1.17807053e-01,
4558   1.79210510e-01, 7.50000000e-01, 9.65415148e-02, 2.00316511e-01,
4559   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 6.99430663e-02},
4560  {0.00000000e+00, 8.27084092e-01, 3.53305100e-01, 6.77518036e-02,
4561   1.99709663e-01, 1.30340902e-01, 5.14073961e-02, 1.35075690e-01,
4562   8.61653901e-02, 4.44355269e-01, 3.36316040e-01, 1.02884887e-01,
4563   2.62669188e-01, 5.31363673e-01, 2.40194503e-01, 1.50331260e-01,
4564   1.06409795e-01, 1.14463515e+00, 1.16950751e+01, 3.90871695e-01,
4565   1.25703039e-02, 7.50000000e-01, 1.11995399e-01, 1.39052321e-01,
4566   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 2.05920141e-01},
4567  {0.00000000e+00, 4.77504036e-01, 6.71234492e-02, 1.32369559e-01,
4568   6.47860871e-02, 1.09854687e-01, 6.66400959e-02, 1.48994667e-01,
4569   1.14978024e-01, 1.93788392e+00, 4.62631009e-02, 4.62744892e-01,
4570   6.30878126e-01, 6.98330827e-02, 1.40453450e-01, 1.02742037e-01,
4571   7.42726505e-02, 1.17807053e-01, 3.90871695e-01, 1.16090589e+01,
4572   5.05672115e-03, 7.50000000e-01, 8.04763342e-02, 1.06755129e-01,
4573   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 9.07853260e-01},
4574  {0.00000000e+00, 9.76867708e-03, 3.23783774e-02, 4.67559620e-03,
4575   5.42804139e-03, 3.23568839e-03, 2.13219283e-01, 5.68401675e-03,
4576   8.12035191e-02, 9.23811792e-03, 1.75142268e-02, 1.27405990e-01,
4577   1.29243603e-02, 6.36210916e-02, 9.02230244e-03, 1.20726953e-02,
4578   5.17051285e-01, 1.79210510e-01, 1.25703039e-02, 5.05672115e-03,
4579   8.86903633e+01, 7.50000000e-01, 1.73378233e-01, 7.08668846e-03,
4580   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 9.17500230e-02},
4581  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4582   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4583   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4584   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4585   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4586   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4587   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 7.50000000e-01},
4588  {0.00000000e+00, 6.99222384e-02, 1.13742904e-01, 2.57579768e-01,
4589   1.97046510e-02, 5.65446816e-02, 1.78617980e+00, 9.25861867e-03,
4590   3.23746871e-01, 1.18573178e-01, 4.16645387e-02, 9.50388211e-02,
4591   2.12719960e-02, 2.22758622e-01, 9.80486654e-03, 1.69239569e-02,
4592   3.01584225e-02, 9.65415148e-02, 1.11995399e-01, 8.04763342e-02,
4593   1.73378233e-01, 7.50000000e-01, 2.84454162e+01, 3.92787209e-02,
4594   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 1.02140077e-01},
4595  {0.00000000e+00, 3.58158006e-01, 9.91005473e-01, 7.98640138e-03,
4596   1.50786644e+00, 8.36539662e+00, 9.33613946e-03, 1.71822465e-01,
4597   6.94918113e-01, 1.15136508e-01, 2.95037286e-01, 1.04757148e-01,
4598   1.70582240e-01, 3.91824098e-01, 2.50506944e-01, 8.75457039e+00,
4599   2.79081365e-01, 2.00316511e-01, 1.39052321e-01, 1.06755129e-01,
4600   7.08668846e-03, 7.50000000e-01, 3.92787209e-02, 8.53499117e+00,
4601   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 1.07889016e-01},
4602  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4603   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4604   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4605   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4606   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4607   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4608   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 7.50000000e-01},
4609  {0.00000000e+00, 3.00000000e-03, 3.00000000e-03, 3.00000000e-03,
4610   3.00000000e-03, 3.00000000e-03, 3.00000000e-03, 3.00000000e-03,
4611   3.00000000e-03, 3.00000000e-03, 3.00000000e-03, 3.00000000e-03,
4612   3.00000000e-03, 3.00000000e-03, 3.00000000e-03, 3.00000000e-03,
4613   3.00000000e-03, 3.00000000e-03, 3.00000000e-03, 3.00000000e-03,
4614   3.00000000e-03, 3.00000000e-03, 3.00000000e-03, 3.00000000e-03,
4615   3.00000000e-03, 1.33300000e+00, 3.00000000e-03, 3.00000000e-03},
4616  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4617   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4618   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4619   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4620   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4621   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4622   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 7.50000000e-01},
4623  {0.00000000e+00, 1.40431646e-01, 7.21274943e-02, 4.01312493e-02,
4624   3.37687752e-02, 7.50595678e-02, 4.32977029e-01, 2.67022462e-02,
4625   9.92432853e-02, 6.07207247e+00, 8.07975645e-02, 7.19029657e+00,
4626   1.10650779e+00, 1.16595604e-01, 7.92594202e-02, 1.50394300e-01,
4627   8.49660454e-02, 6.99430663e-02, 2.05920141e-01, 9.07853260e-01,
4628   9.17500230e-02, 7.50000000e-01, 1.02140077e-01, 1.07889016e-01,
4629   7.50000000e-01, 3.00000000e-03, 7.50000000e-01, 6.85288369e+00}};
4630 
4631 
4632 /** Underlying frequency ratios for PAM70 */
4633 static const double PAM70_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
4634 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4635   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4636   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4637   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4638   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4639   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4640   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
4641  {0.00000000e+00, 4.89972946e+00, 6.04638890e-01, 2.42067963e-01,
4642   6.18433760e-01, 7.71213936e-01, 1.34833512e-01, 1.01498720e+00,
4643   2.21390981e-01, 4.34566961e-01, 2.49319770e-01, 2.49736666e-01,
4644   3.75829845e-01, 5.88646912e-01, 1.03045017e+00, 4.65602795e-01,
4645   2.26934456e-01, 1.34964157e+00, 1.32707297e+00, 8.08640731e-01,
4646   4.32618091e-02, 7.50000000e-01, 1.54222102e-01, 6.38034395e-01,
4647   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 3.05507349e-01},
4648  {0.00000000e+00, 6.04638890e-01, 5.42142610e+00, 6.60540784e-02,
4649   5.88929014e+00, 2.24885858e+00, 7.88958522e-02, 6.48829213e-01,
4650   1.09845328e+00, 2.52789787e-01, 7.77906911e-01, 1.19715714e-01,
4651   1.39730820e-01, 4.87904539e+00, 2.73736473e-01, 7.90138593e-01,
4652   2.53425041e-01, 9.54703234e-01, 6.53688648e-01, 1.85063408e-01,
4653   7.80441148e-02, 7.50000000e-01, 2.23329473e-01, 1.61317606e+00,
4654   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.59869478e-01},
4655  {0.00000000e+00, 2.42067963e-01, 6.60540784e-02, 2.48333286e+01,
4656   3.97130183e-02, 3.87120726e-02, 5.48382532e-02, 1.15679023e-01,
4657   1.64834856e-01, 2.46442788e-01, 3.83065039e-02, 3.01944614e-02,
4658   4.42379868e-02, 9.65904773e-02, 1.58823055e-01, 3.93861754e-02,
4659   1.51302811e-01, 6.65193229e-01, 1.86417892e-01, 2.74442219e-01,
4660   2.22251459e-02, 7.50000000e-01, 5.23320532e-01, 3.90058338e-02,
4661   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 9.54452197e-02},
4662  {0.00000000e+00, 6.18433760e-01, 5.88929014e+00, 3.97130183e-02,
4663   8.89965209e+00, 3.35659301e+00, 3.36340414e-02, 6.39387415e-01,
4664   5.99746161e-01, 1.93031482e-01, 4.83846284e-01, 6.35580693e-02,
4665   1.03502951e-01, 2.39946804e+00, 2.12686642e-01, 9.22524100e-01,
4666   1.38560979e-01, 5.99713481e-01, 4.42110174e-01, 1.72922381e-01,
4667   2.64171458e-02, 7.50000000e-01, 7.98817496e-02, 2.29587193e+00,
4668   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.02625370e-01},
4669  {0.00000000e+00, 7.71213936e-01, 2.24885858e+00, 3.87120726e-02,
4670   3.35659301e+00, 8.65385421e+00, 3.82398528e-02, 4.91841782e-01,
4671   4.80150693e-01, 2.83623924e-01, 4.66181910e-01, 1.17487568e-01,
4672   2.12426533e-01, 9.64695360e-01, 3.47480663e-01, 2.25815498e+00,
4673   1.78914910e-01, 4.78627630e-01, 3.38114944e-01, 2.46972907e-01,
4674   1.89756038e-02, 7.50000000e-01, 1.19141830e-01, 5.86672974e+00,
4675   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.67617543e-01},
4676  {0.00000000e+00, 1.34833512e-01, 7.88958522e-02, 5.48382532e-02,
4677   3.36340414e-02, 3.82398528e-02, 1.74546228e+01, 1.00136016e-01,
4678   2.76577280e-01, 8.45971180e-01, 4.12894272e-02, 8.23804865e-01,
4679   5.08442478e-01, 1.31366508e-01, 8.91727264e-02, 5.25046736e-02,
4680   9.93639027e-02, 2.15603624e-01, 1.37600314e-01, 2.07856659e-01,
4681   4.52242030e-01, 7.50000000e-01, 3.37849562e+00, 4.44561913e-02,
4682   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 8.30493328e-01},
4683  {0.00000000e+00, 1.01498720e+00, 6.48829213e-01, 1.15679023e-01,
4684   6.39387415e-01, 4.91841782e-01, 1.00136016e-01, 7.30864335e+00,
4685   1.45138751e-01, 1.07004308e-01, 2.09861286e-01, 8.09786598e-02,
4686   1.44276056e-01, 6.59774806e-01, 3.08399509e-01, 2.37177521e-01,
4687   1.22086776e-01, 9.64187863e-01, 3.70424893e-01, 3.12986176e-01,
4688   2.68996967e-02, 7.50000000e-01, 4.37757319e-02, 3.80863925e-01,
4689   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 8.88316375e-02},
4690  {0.00000000e+00, 2.21390981e-01, 1.09845328e+00, 1.64834856e-01,
4691   5.99746161e-01, 4.80150693e-01, 2.76577280e-01, 1.45138751e-01,
4692   1.64223829e+01, 1.39752446e-01, 3.35085062e-01, 2.59072609e-01,
4693   1.22395235e-01, 1.67658945e+00, 4.92867985e-01, 2.18832010e+00,
4694   1.05779530e+00, 3.26721114e-01, 2.30266854e-01, 2.33270842e-01,
4695   1.86063506e-01, 7.50000000e-01, 6.11386658e-01, 1.22453853e+00,
4696   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 2.23068949e-01},
4697  {0.00000000e+00, 4.34566961e-01, 2.52789787e-01, 2.46442788e-01,
4698   1.93031482e-01, 2.83623924e-01, 8.45971180e-01, 1.07004308e-01,
4699   1.39752446e-01, 1.17505537e+01, 2.66278255e-01, 1.19239531e+00,
4700   1.36908981e+00, 3.22065793e-01, 1.59577365e-01, 1.89299534e-01,
4701   3.01479599e-01, 2.53646367e-01, 7.61111058e-01, 3.00374358e+00,
4702   4.36969076e-02, 7.50000000e-01, 2.80489781e-01, 2.42519143e-01,
4703   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 4.37821344e+00},
4704  {0.00000000e+00, 2.49319770e-01, 7.77906911e-01, 3.83065039e-02,
4705   4.83846284e-01, 4.66181910e-01, 4.12894272e-02, 2.09861286e-01,
4706   3.35085062e-01, 2.66278255e-01, 7.61026217e+00, 1.52754534e-01,
4707   9.47937549e-01, 1.11880255e+00, 2.56118662e-01, 7.21669881e-01,
4708   1.93666556e+00, 5.20459614e-01, 6.20196625e-01, 1.38845936e-01,
4709   7.91911207e-02, 7.50000000e-01, 1.00771644e-01, 5.77518724e-01,
4710   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.87009175e-01},
4711  {0.00000000e+00, 2.49736666e-01, 1.19715714e-01, 3.01944614e-02,
4712   6.35580693e-02, 1.17487568e-01, 8.23804865e-01, 8.09786598e-02,
4713   2.59072609e-01, 1.19239531e+00, 1.52754534e-01, 8.22843955e+00,
4714   2.12939550e+00, 1.84817584e-01, 1.98778178e-01, 3.50784854e-01,
4715   1.37359422e-01, 1.48574310e-01, 2.40326213e-01, 9.08401895e-01,
4716   2.67168548e-01, 7.50000000e-01, 2.38980900e-01, 2.19154102e-01,
4717   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 6.10538395e+00},
4718  {0.00000000e+00, 3.75829845e-01, 1.39730820e-01, 4.42379868e-02,
4719   1.03502951e-01, 2.12426533e-01, 5.08442478e-01, 1.44276056e-01,
4720   1.22395235e-01, 1.36908981e+00, 9.47937549e-01, 2.12939550e+00,
4721   2.85861616e+01, 1.81728699e-01, 1.75926195e-01, 4.86044449e-01,
4722   4.88080973e-01, 3.18976045e-01, 4.97701201e-01, 1.13284160e+00,
4723   5.97810639e-02, 7.50000000e-01, 9.73038916e-02, 3.31664034e-01,
4724   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.89998090e+00},
4725  {0.00000000e+00, 5.88646912e-01, 4.87904539e+00, 9.65904773e-02,
4726   2.39946804e+00, 9.64695360e-01, 1.31366508e-01, 6.59774806e-01,
4727   1.67658945e+00, 3.22065793e-01, 1.11880255e+00, 1.84817584e-01,
4728   1.81728699e-01, 7.75354485e+00, 3.44509706e-01, 6.36668056e-01,
4729   3.86583495e-01, 1.36623218e+00, 8.98965212e-01, 1.99138136e-01,
4730   1.37893708e-01, 7.50000000e-01, 3.89624106e-01, 8.21747280e-01,
4731   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 2.26230851e-01},
4732  {0.00000000e+00, 1.03045017e+00, 2.73736473e-01, 1.58823055e-01,
4733   2.12686642e-01, 3.47480663e-01, 8.91727264e-02, 3.08399509e-01,
4734   4.92867985e-01, 1.59577365e-01, 2.56118662e-01, 1.98778178e-01,
4735   1.75926195e-01, 3.44509706e-01, 1.18714088e+01, 6.84263791e-01,
4736   5.26778639e-01, 9.79291808e-01, 5.30644206e-01, 3.07279290e-01,
4737   4.18182164e-02, 7.50000000e-01, 4.66910129e-02, 4.94244365e-01,
4738   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.86949727e-01},
4739  {0.00000000e+00, 4.65602795e-01, 7.90138593e-01, 3.93861754e-02,
4740   9.22524100e-01, 2.25815498e+00, 5.25046736e-02, 2.37177521e-01,
4741   2.18832010e+00, 1.89299534e-01, 7.21669881e-01, 3.50784854e-01,
4742   4.86044449e-01, 6.36668056e-01, 6.84263791e-01, 1.14706864e+01,
4743   1.02361055e+00, 3.73519396e-01, 3.29322200e-01, 2.32053434e-01,
4744   5.49721446e-02, 7.50000000e-01, 7.38645866e-02, 6.27280154e+00,
4745   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 3.02058283e-01},
4746  {0.00000000e+00, 2.26934456e-01, 2.53425041e-01, 1.51302811e-01,
4747   1.38560979e-01, 1.78914910e-01, 9.93639027e-02, 1.22086776e-01,
4748   1.05779530e+00, 3.01479599e-01, 1.93666556e+00, 1.37359422e-01,
4749   4.88080973e-01, 3.86583495e-01, 5.26778639e-01, 1.02361055e+00,
4750   1.36584013e+01, 6.10010848e-01, 2.83658630e-01, 1.75829089e-01,
4751   9.90780192e-01, 7.50000000e-01, 8.59463892e-02, 5.47017256e-01,
4752   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.86881035e-01},
4753  {0.00000000e+00, 1.34964157e+00, 9.54703234e-01, 6.65193229e-01,
4754   5.99713481e-01, 4.78627630e-01, 2.15603624e-01, 9.64187863e-01,
4755   3.26721114e-01, 2.53646367e-01, 5.20459614e-01, 1.48574310e-01,
4756   3.18976045e-01, 1.36623218e+00, 9.79291808e-01, 3.73519396e-01,
4757   6.10010848e-01, 5.20445832e+00, 1.69490837e+00, 3.03324606e-01,
4758   3.23868004e-01, 7.50000000e-01, 2.08076540e-01, 4.32823454e-01,
4759   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.80278747e-01},
4760  {0.00000000e+00, 1.32707297e+00, 6.53688648e-01, 1.86417892e-01,
4761   4.42110174e-01, 3.38114944e-01, 1.37600314e-01, 3.70424893e-01,
4762   2.30266854e-01, 7.61111058e-01, 6.20196625e-01, 2.40326213e-01,
4763   4.97701201e-01, 8.98965212e-01, 5.30644206e-01, 3.29322200e-01,
4764   2.83658630e-01, 1.69490837e+00, 7.33707214e+00, 7.18561720e-01,
4765   5.45397612e-02, 7.50000000e-01, 2.27833757e-01, 3.34283233e-01,
4766   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 3.97467804e-01},
4767  {0.00000000e+00, 8.08640731e-01, 1.85063408e-01, 2.74442219e-01,
4768   1.72922381e-01, 2.46972907e-01, 2.07856659e-01, 3.12986176e-01,
4769   2.33270842e-01, 3.00374358e+00, 1.38845936e-01, 9.08401895e-01,
4770   1.13284160e+00, 1.99138136e-01, 3.07279290e-01, 2.32053434e-01,
4771   1.75829089e-01, 3.03324606e-01, 7.18561720e-01, 8.21110545e+00,
4772   2.66588959e-02, 7.50000000e-01, 1.80843519e-01, 2.40471284e-01,
4773   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.54065018e+00},
4774  {0.00000000e+00, 4.32618091e-02, 7.80441148e-02, 2.22251459e-02,
4775   2.64171458e-02, 1.89756038e-02, 4.52242030e-01, 2.68996967e-02,
4776   1.86063506e-01, 4.36969076e-02, 7.91911207e-02, 2.67168548e-01,
4777   5.97810639e-02, 1.37893708e-01, 4.18182164e-02, 5.49721446e-02,
4778   9.90780192e-01, 3.23868004e-01, 5.45397612e-02, 2.66588959e-02,
4779   8.06167129e+01, 7.50000000e-01, 3.76692625e-01, 3.46622138e-02,
4780   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 1.99738227e-01},
4781  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4782   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4783   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4784   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4785   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4786   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4787   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 7.50000000e-01},
4788  {0.00000000e+00, 1.54222102e-01, 2.23329473e-01, 5.23320532e-01,
4789   7.98817496e-02, 1.19141830e-01, 3.37849562e+00, 4.37757319e-02,
4790   6.11386658e-01, 2.80489781e-01, 1.00771644e-01, 2.38980900e-01,
4791   9.73038916e-02, 3.89624106e-01, 4.66910129e-02, 7.38645866e-02,
4792   8.59463892e-02, 2.08076540e-01, 2.27833757e-01, 1.80843519e-01,
4793   3.76692625e-01, 7.50000000e-01, 2.31438270e+01, 9.94108657e-02,
4794   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 2.51505787e-01},
4795  {0.00000000e+00, 6.38034395e-01, 1.61317606e+00, 3.90058338e-02,
4796   2.29587193e+00, 5.86672974e+00, 4.44561913e-02, 3.80863925e-01,
4797   1.22453853e+00, 2.42519143e-01, 5.77518724e-01, 2.19154102e-01,
4798   3.31664034e-01, 8.21747280e-01, 4.94244365e-01, 6.27280154e+00,
4799   5.47017256e-01, 4.32823454e-01, 3.34283233e-01, 2.40471284e-01,
4800   3.46622138e-02, 7.50000000e-01, 9.94108657e-02, 6.04368813e+00,
4801   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 2.26204268e-01},
4802  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4803   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4804   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4805   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4806   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4807   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4808   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 7.50000000e-01},
4809  {0.00000000e+00, 2.00000000e-02, 2.00000000e-02, 2.00000000e-02,
4810   2.00000000e-02, 2.00000000e-02, 2.00000000e-02, 2.00000000e-02,
4811   2.00000000e-02, 2.00000000e-02, 2.00000000e-02, 2.00000000e-02,
4812   2.00000000e-02, 2.00000000e-02, 2.00000000e-02, 2.00000000e-02,
4813   2.00000000e-02, 2.00000000e-02, 2.00000000e-02, 2.00000000e-02,
4814   2.00000000e-02, 2.00000000e-02, 2.00000000e-02, 2.00000000e-02,
4815   2.00000000e-02, 1.33300000e+00, 2.00000000e-02, 2.00000000e-02},
4816  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4817   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4818   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4819   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4820   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4821   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4822   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 7.50000000e-01},
4823  {0.00000000e+00, 3.05507349e-01, 1.59869478e-01, 9.54452197e-02,
4824   1.02625370e-01, 1.67617543e-01, 8.30493328e-01, 8.88316375e-02,
4825   2.23068949e-01, 4.37821344e+00, 1.87009175e-01, 6.10538395e+00,
4826   1.89998090e+00, 2.26230851e-01, 1.86949727e-01, 3.02058283e-01,
4827   1.86881035e-01, 1.80278747e-01, 3.97467804e-01, 1.54065018e+00,
4828   1.99738227e-01, 7.50000000e-01, 2.51505787e-01, 2.26204268e-01,
4829   7.50000000e-01, 2.00000000e-02, 7.50000000e-01, 5.58422761e+00}};
4830 
4831 
4832 /** Underlying frequency ratios for PAM250 */
4833 static const double PAM250_FREQRATIOS[POSITAA_SIZE][POSITAA_SIZE] =
4834 {{0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4835   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4836   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4837   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4838   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4839   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
4840   0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00},
4841  {0.00000000e+00, 1.51578006e+00, 1.05606466e+00, 6.26687137e-01,
4842   1.07002228e+00, 1.07474947e+00, 4.46290560e-01, 1.33923306e+00,
4843   7.32178470e-01, 8.88728816e-01, 7.66227814e-01, 6.46341735e-01,
4844   7.70359541e-01, 1.03988401e+00, 1.29408826e+00, 9.03456780e-01,
4845   7.00798809e-01, 1.28966428e+00, 1.31725380e+00, 1.04499203e+00,
4846   2.63609841e-01, 7.50000000e-01, 4.49686798e-01, 1.00010336e+00,
4847   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 7.19479599e-01},
4848  {0.00000000e+00, 1.05606466e+00, 1.84257846e+00, 3.65113184e-01,
4849   2.05195422e+00, 1.82470118e+00, 3.54071966e-01, 1.11918465e+00,
4850   1.29683470e+00, 6.16970770e-01, 1.13010166e+00, 4.52559218e-01,
4851   6.04775077e-01, 1.59985542e+00, 8.46142888e-01, 1.33890747e+00,
4852   8.61808201e-01, 1.11706882e+00, 1.03197349e+00, 6.37811920e-01,
4853   2.96793416e-01, 7.50000000e-01, 4.85608019e-01, 1.61300149e+00,
4854   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.02168751e-01},
4855  {0.00000000e+00, 6.26687137e-01, 3.65113184e-01, 1.56285624e+01,
4856   3.06772262e-01, 2.94964746e-01, 3.70976416e-01, 4.59297624e-01,
4857   4.51836855e-01, 5.87603719e-01, 2.86099293e-01, 2.47791243e-01,
4858   2.99408166e-01, 4.32746060e-01, 5.27421501e-01, 2.89534285e-01,
4859   4.30504374e-01, 9.89678273e-01, 6.01385571e-01, 6.38902701e-01,
4860   1.68818010e-01, 7.50000000e-01, 1.07830459e+00, 2.92598254e-01,
4861   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 3.50326241e-01},
4862  {0.00000000e+00, 1.07002228e+00, 2.05195422e+00, 3.06772262e-01,
4863   2.43292288e+00, 2.19715052e+00, 2.73911818e-01, 1.14726861e+00,
4864   1.17343465e+00, 5.79909835e-01, 1.01987501e+00, 3.98183329e-01,
4865   5.48083233e-01, 1.61030872e+00, 8.05577240e-01, 1.46152937e+00,
4866   7.42874842e-01, 1.06886174e+00, 9.67471640e-01, 6.11601820e-01,
4867   2.12712296e-01, 7.50000000e-01, 3.69025897e-01, 1.87658077e+00,
4868   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 4.53017475e-01},
4869  {0.00000000e+00, 1.07474947e+00, 1.82470118e+00, 2.94964746e-01,
4870   2.19715052e+00, 2.41404373e+00, 2.87098831e-01, 1.04389169e+00,
4871   1.16525001e+00, 6.26339428e-01, 9.87756703e-01, 4.63568053e-01,
4872   6.13603630e-01, 1.39293185e+00, 8.79669521e-01, 1.77158803e+00,
4873   7.82149443e-01, 9.98597151e-01, 9.13853001e-01, 6.60440693e-01,
4874   2.00637717e-01, 7.50000000e-01, 3.71943861e-01, 2.13407372e+00,
4875   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.12682678e-01},
4876  {0.00000000e+00, 4.46290560e-01, 3.54071966e-01, 3.70976416e-01,
4877   2.73911818e-01, 2.87098831e-01, 8.02764197e+00, 3.32339414e-01,
4878   6.59545216e-01, 1.26203255e+00, 2.98137999e-01, 1.51752623e+00,
4879   1.04274830e+00, 4.46999215e-01, 3.50828021e-01, 3.43119584e-01,
4880   3.58749728e-01, 4.78353203e-01, 4.88459165e-01, 7.66309017e-01,
4881   1.07668873e+00, 7.50000000e-01, 4.97590308e+00, 3.11511613e-01,
4882   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 1.44043358e+00},
4883  {0.00000000e+00, 1.33923306e+00, 1.11918465e+00, 4.59297624e-01,
4884   1.14726861e+00, 1.04389169e+00, 3.32339414e-01, 2.99056680e+00,
4885   6.15552047e-01, 5.57103314e-01, 6.78509416e-01, 3.94686522e-01,
4886   5.25369171e-01, 1.08662777e+00, 8.94077901e-01, 7.57447784e-01,
4887   5.54986868e-01, 1.27845679e+00, 9.98770702e-01, 7.34634729e-01,
4888   2.00363838e-01, 7.50000000e-01, 2.99613619e-01, 9.19064864e-01,
4889   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 4.43694156e-01},
4890  {0.00000000e+00, 7.32178470e-01, 1.29683470e+00, 4.51836855e-01,
4891   1.17343465e+00, 1.16525001e+00, 6.59545216e-01, 6.15552047e-01,
4892   4.47513035e+00, 5.70614299e-01, 9.90160946e-01, 6.20055020e-01,
4893   6.09441413e-01, 1.43988866e+00, 9.46471632e-01, 1.96194975e+00,
4894   1.43036819e+00, 8.30226277e-01, 7.40733381e-01, 5.96692220e-01,
4895   5.44285116e-01, 7.50000000e-01, 9.78877039e-01, 1.51243666e+00,
4896   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 6.05136779e-01},
4897  {0.00000000e+00, 8.88728816e-01, 6.16970770e-01, 5.87603719e-01,
4898   5.79909835e-01, 6.26339428e-01, 1.26203255e+00, 5.57103314e-01,
4899   5.70614299e-01, 2.83022396e+00, 6.40800116e-01, 1.74919442e+00,
4900   1.64986005e+00, 6.59934398e-01, 6.27243837e-01, 6.25316723e-01,
4901   6.29014923e-01, 7.22513707e-01, 1.01665478e+00, 2.33821719e+00,
4902   3.02670201e-01, 7.50000000e-01, 7.99863687e-01, 6.25893752e-01,
4903   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 2.07538421e+00},
4904  {0.00000000e+00, 7.66227814e-01, 1.13010166e+00, 2.86099293e-01,
4905   1.01987501e+00, 9.87756703e-01, 2.98137999e-01, 6.78509416e-01,
4906   9.90160946e-01, 6.40800116e-01, 2.92620120e+00, 5.18814877e-01,
4907   1.09961986e+00, 1.25788411e+00, 7.70516817e-01, 1.18387275e+00,
4908   2.18168472e+00, 9.61645918e-01, 9.95647751e-01, 5.70096500e-01,
4909   4.50323287e-01, 7.50000000e-01, 3.59829368e-01, 1.07322036e+00,
4910   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.55622697e-01},
4911  {0.00000000e+00, 6.46341735e-01, 4.52559218e-01, 2.47791243e-01,
4912   3.98183329e-01, 4.63568053e-01, 1.51752623e+00, 3.94686522e-01,
4913   6.20055020e-01, 1.74919442e+00, 5.18814877e-01, 3.92994485e+00,
4914   2.33771776e+00, 5.15595552e-01, 5.56038228e-01, 6.65507525e-01,
4915   5.01008003e-01, 5.24107036e-01, 6.77040993e-01, 1.53178711e+00,
4916   6.46886104e-01, 7.50000000e-01, 8.14904569e-01, 5.51569446e-01,
4917   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 3.27192533e+00},
4918  {0.00000000e+00, 7.70359541e-01, 6.04775077e-01, 2.99408166e-01,
4919   5.48083233e-01, 6.13603630e-01, 1.04274830e+00, 5.25369171e-01,
4920   6.09441413e-01, 1.64986005e+00, 1.09961986e+00, 2.33771776e+00,
4921   4.40351686e+00, 6.70496227e-01, 6.21012433e-01, 7.95710012e-01,
4922   9.04471250e-01, 6.98581457e-01, 8.73067477e-01, 1.51039751e+00,
4923   3.74941590e-01, 7.50000000e-01, 5.67675865e-01, 6.92962139e-01,
4924   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 2.13016362e+00},
4925  {0.00000000e+00, 1.03988401e+00, 1.59985542e+00, 4.32746060e-01,
4926   1.61030872e+00, 1.39293185e+00, 4.46999215e-01, 1.08662777e+00,
4927   1.43988866e+00, 6.59934398e-01, 1.25788411e+00, 5.15595552e-01,
4928   6.70496227e-01, 1.58773724e+00, 8.93169424e-01, 1.19675558e+00,
4929   9.99684066e-01, 1.17295383e+00, 1.10674855e+00, 6.68196499e-01,
4930   3.94266130e-01, 7.50000000e-01, 6.20758168e-01, 1.30744195e+00,
4931   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.59148347e-01},
4932  {0.00000000e+00, 1.29408826e+00, 8.46142888e-01, 5.27421501e-01,
4933   8.05577240e-01, 8.79669521e-01, 3.50828021e-01, 8.94077901e-01,
4934   9.46471632e-01, 6.27243837e-01, 7.70516817e-01, 5.56038228e-01,
4935   6.21012433e-01, 8.93169424e-01, 3.84141803e+00, 1.05550534e+00,
4936   9.60208581e-01, 1.24349521e+00, 1.07552180e+00, 7.58279920e-01,
4937   2.75343404e-01, 7.50000000e-01, 3.20901839e-01, 9.56295438e-01,
4938   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.77523805e-01},
4939  {0.00000000e+00, 9.03456780e-01, 1.33890747e+00, 2.89534285e-01,
4940   1.46152937e+00, 1.77158803e+00, 3.43119584e-01, 7.57447784e-01,
4941   1.96194975e+00, 6.25316723e-01, 1.18387275e+00, 6.65507525e-01,
4942   7.95710012e-01, 1.19675558e+00, 1.05550534e+00, 2.54088209e+00,
4943   1.33504131e+00, 8.89983529e-01, 8.32948914e-01, 6.49448913e-01,
4944   3.35176014e-01, 7.50000000e-01, 3.94549334e-01, 2.10683180e+00,
4945   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 6.53380354e-01},
4946  {0.00000000e+00, 7.00798809e-01, 8.61808201e-01, 4.30504374e-01,
4947   7.42874842e-01, 7.82149443e-01, 3.58749728e-01, 5.54986868e-01,
4948   1.43036819e+00, 6.29014923e-01, 2.18168472e+00, 5.01008003e-01,
4949   9.04471250e-01, 9.99684066e-01, 9.60208581e-01, 1.33504131e+00,
4950   4.07760419e+00, 9.28286966e-01, 8.20208528e-01, 5.61449723e-01,
4951   1.65111328e+00, 7.50000000e-01, 3.78768704e-01, 1.02308924e+00,
4952   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.39632804e-01},
4953  {0.00000000e+00, 1.28966428e+00, 1.11706882e+00, 9.89678273e-01,
4954   1.06886174e+00, 9.98597151e-01, 4.78353203e-01, 1.27845679e+00,
4955   8.30226277e-01, 7.22513707e-01, 9.61645918e-01, 5.24107036e-01,
4956   6.98581457e-01, 1.17295383e+00, 1.24349521e+00, 8.89983529e-01,
4957   9.28286966e-01, 1.44062735e+00, 1.36207698e+00, 7.99071364e-01,
4958   5.65535441e-01, 7.50000000e-01, 5.19882078e-01, 9.51265394e-01,
4959   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.83974254e-01},
4960  {0.00000000e+00, 1.31725380e+00, 1.03197349e+00, 6.01385571e-01,
4961   9.67471640e-01, 9.13853001e-01, 4.88459165e-01, 9.98770702e-01,
4962   7.40733381e-01, 1.01665478e+00, 9.95647751e-01, 6.77040993e-01,
4963   8.73067477e-01, 1.10674855e+00, 1.07552180e+00, 8.32948914e-01,
4964   8.20208528e-01, 1.36207698e+00, 1.80640078e+00, 1.06764169e+00,
4965   3.05841935e-01, 7.50000000e-01, 5.30232118e-01, 8.78596534e-01,
4966   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 7.79516037e-01},
4967  {0.00000000e+00, 1.04499203e+00, 6.37811920e-01, 6.38902701e-01,
4968   6.11601820e-01, 6.60440693e-01, 7.66309017e-01, 7.34634729e-01,
4969   5.96692220e-01, 2.33821719e+00, 5.70096500e-01, 1.53178711e+00,
4970   1.51039751e+00, 6.68196499e-01, 7.58279920e-01, 6.49448913e-01,
4971   5.61449723e-01, 7.99071364e-01, 1.06764169e+00, 2.69825619e+00,
4972   2.36794202e-01, 7.50000000e-01, 5.65836205e-01, 6.55650683e-01,
4973   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 1.77511928e+00},
4974  {0.00000000e+00, 2.63609841e-01, 2.96793416e-01, 1.68818010e-01,
4975   2.12712296e-01, 2.00637717e-01, 1.07668873e+00, 2.00363838e-01,
4976   5.44285116e-01, 3.02670201e-01, 4.50323287e-01, 6.46886104e-01,
4977   3.74941590e-01, 3.94266130e-01, 2.75343404e-01, 3.35176014e-01,
4978   1.65111328e+00, 5.65535441e-01, 3.05841935e-01, 2.36794202e-01,
4979   5.26606678e+01, 7.50000000e-01, 9.69642510e-01, 2.59266956e-01,
4980   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.43022417e-01},
4981  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4982   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4983   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4984   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4985   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4986   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
4987   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 7.50000000e-01},
4988  {0.00000000e+00, 4.49686798e-01, 4.85608019e-01, 1.07830459e+00,
4989   3.69025897e-01, 3.71943861e-01, 4.97590308e+00, 2.99613619e-01,
4990   9.78877039e-01, 7.99863687e-01, 3.59829368e-01, 8.14904569e-01,
4991   5.67675865e-01, 6.20758168e-01, 3.20901839e-01, 3.94549334e-01,
4992   3.78768704e-01, 5.19882078e-01, 5.30232118e-01, 5.65836205e-01,
4993   9.69642510e-01, 7.50000000e-01, 1.03387565e+01, 3.81794898e-01,
4994   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 8.10366134e-01},
4995  {0.00000000e+00, 1.00010336e+00, 1.61300149e+00, 2.92598254e-01,
4996   1.87658077e+00, 2.13407372e+00, 3.11511613e-01, 9.19064864e-01,
4997   1.51243666e+00, 6.25893752e-01, 1.07322036e+00, 5.51569446e-01,
4998   6.92962139e-01, 1.30744195e+00, 9.56295438e-01, 2.10683180e+00,
4999   1.02308924e+00, 9.51265394e-01, 8.78596534e-01, 6.55650683e-01,
5000   2.59266956e-01, 7.50000000e-01, 3.81794898e-01, 2.12220220e+00,
5001   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 5.73996058e-01},
5002  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5003   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5004   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5005   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5006   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5007   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5008   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 7.50000000e-01},
5009  {0.00000000e+00, 1.70000000e-01, 1.70000000e-01, 1.70000000e-01,
5010   1.70000000e-01, 1.70000000e-01, 1.70000000e-01, 1.70000000e-01,
5011   1.70000000e-01, 1.70000000e-01, 1.70000000e-01, 1.70000000e-01,
5012   1.70000000e-01, 1.70000000e-01, 1.70000000e-01, 1.70000000e-01,
5013   1.70000000e-01, 1.70000000e-01, 1.70000000e-01, 1.70000000e-01,
5014   1.70000000e-01, 1.70000000e-01, 1.70000000e-01, 1.70000000e-01,
5015   1.70000000e-01, 1.33300000e+00, 1.70000000e-01, 1.70000000e-01},
5016  {0.00000000e+00, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5017   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5018   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5019   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5020   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5021   7.50000000e-01, 7.50000000e-01, 7.50000000e-01, 7.50000000e-01,
5022   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 7.50000000e-01},
5023  {0.00000000e+00, 7.19479599e-01, 5.02168751e-01, 3.50326241e-01,
5024   4.53017475e-01, 5.12682678e-01, 1.44043358e+00, 4.43694156e-01,
5025   6.05136779e-01, 2.07538421e+00, 5.55622697e-01, 3.27192533e+00,
5026   2.13016362e+00, 5.59148347e-01, 5.77523805e-01, 6.53380354e-01,
5027   5.39632804e-01, 5.83974254e-01, 7.79516037e-01, 1.77511928e+00,
5028   5.43022417e-01, 7.50000000e-01, 8.10366134e-01, 5.73996058e-01,
5029   7.50000000e-01, 1.70000000e-01, 7.50000000e-01, 2.91088108e+00}};
5030 
5031 
5032 FreqRatios*
5033 PSIMatrixFrequencyRatiosNew(const char* matrix_name)
5034 {
5035     unsigned int i, j;          /* loop indices */
5036     FreqRatios* retval = NULL;  /* the return value */
5037 
5038     ASSERT(matrix_name);
5039 
5040     retval = (FreqRatios*) Malloc(sizeof(FreqRatios));
5041     if ( !retval ) {
5042         return NULL;
5043     }
5044 
5045     retval->data = (double**) Malloc(sizeof(double*)*PROTEIN_ALPHABET);
5046     if ( !retval->data ) {
5047         return PSIMatrixFrequencyRatiosFree(retval);
5048     }
5049 
5050     for (i = 0; i < PROTEIN_ALPHABET; i++) {
5051         retval->data[i] = (double*) Malloc(sizeof(double)*PROTEIN_ALPHABET);
5052         if ( !retval->data[i] ) {
5053             for (j = 0; j < i; j++) {
5054                 retval->data[j] = MemFree(retval->data[j]);
5055             }
5056             return PSIMatrixFrequencyRatiosFree(retval);
5057         }
5058     }
5059 
5060     if ( !strcmp(matrix_name, "BLOSUM62") ||
5061          !strcmp(matrix_name, "BLOSUM62_20")) {
5062         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5063             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5064                 retval->data[i][j] = BLOSUM62_FREQRATIOS[i][j];
5065             }
5066         }
5067         retval->bit_scale_factor = 2;
5068     } else if ( !strcmp(matrix_name, "BLOSUM62_20A")) {
5069         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5070             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5071                 retval->data[i][j] = 
5072                     BLOSUM62_20A_SCALE_MULTIPLIER * BLOSUM62_FREQRATIOS[i][j];
5073             }
5074         }
5075         retval->bit_scale_factor = 2;
5076     } else if ( !strcmp(matrix_name, "BLOSUM62_20B")) {
5077         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5078             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5079                 retval->data[i][j] =
5080                     BLOSUM62_20B_SCALE_MULTIPLIER * BLOSUM62_FREQRATIOS[i][j];
5081             }
5082         }
5083         retval->bit_scale_factor = 2;
5084     } else if ( !strcmp(matrix_name, "BLOSUM45") ) {
5085         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5086             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5087                 retval->data[i][j] = BLOSUM45_FREQRATIOS[i][j];
5088             }
5089         }
5090         retval->bit_scale_factor = 3;
5091     } else if ( !strcmp(matrix_name, "BLOSUM80") ) {
5092         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5093             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5094                 retval->data[i][j] = BLOSUM80_FREQRATIOS[i][j];
5095             }
5096         }
5097         retval->bit_scale_factor = 2;
5098     } else if ( !strcmp(matrix_name, "BLOSUM50") ) {
5099         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5100             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5101                 retval->data[i][j] = BLOSUM50_FREQRATIOS[i][j];
5102             }
5103         }
5104         retval->bit_scale_factor = 2;
5105     } else if ( !strcmp(matrix_name, "BLOSUM90") ) {
5106         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5107             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5108                 retval->data[i][j] = BLOSUM90_FREQRATIOS[i][j];
5109             }
5110         }
5111         retval->bit_scale_factor = 2;
5112     } else if ( !strcmp(matrix_name, "PAM30") ) {
5113         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5114             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5115                 retval->data[i][j] = PAM30_FREQRATIOS[i][j];
5116             }
5117         }
5118         retval->bit_scale_factor = 2;
5119     } else if ( !strcmp(matrix_name, "PAM70") ) {
5120         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5121             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5122                 retval->data[i][j] = PAM70_FREQRATIOS[i][j];
5123             }
5124         }
5125         retval->bit_scale_factor = 2;
5126     } else if ( !strcmp(matrix_name, "PAM250") ) {
5127         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5128             for (j = 0; j < PROTEIN_ALPHABET; j++) {
5129                 retval->data[i][j] = PAM250_FREQRATIOS[i][j];
5130             }
5131         }
5132         retval->bit_scale_factor = 2;
5133     } else {
5134         retval = PSIMatrixFrequencyRatiosFree(retval);
5135     }
5136 
5137     return retval;
5138 }
5139 
5140 FreqRatios*
5141 PSIMatrixFrequencyRatiosFree(FreqRatios* freq_ratios)
5142 {
5143     if ( !freq_ratios )
5144         return NULL;
5145 
5146     if (freq_ratios->data) {
5147         Uint4 i;
5148         for (i = 0; i < PROTEIN_ALPHABET; i++) {
5149             freq_ratios->data[i] = MemFree(freq_ratios->data[i]);
5150         }
5151         freq_ratios->data = MemFree(freq_ratios->data);
5152     }
5153 
5154     freq_ratios = MemFree(freq_ratios);
5155     return NULL;
5156 }
5157 
5158 /* END of copied code */
5159 /****************************************************************************/
5160 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.