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