Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.analysis.scoremodels

File ScoreMatrixTest.java

 

Code metrics

18
260
24
1
710
496
34
0.13
10.83
24
1.42

Classes

Class Line # Actions
ScoreMatrixTest 28 260 34
1.0100%
 

Contributing tests

This file is covered by 22 tests. .

Source view

1    package jalview.analysis.scoremodels;
2   
3    import static org.testng.Assert.assertEquals;
4    import static org.testng.Assert.assertFalse;
5    import static org.testng.Assert.assertNotEquals;
6    import static org.testng.Assert.assertNotNull;
7    import static org.testng.Assert.assertNotSame;
8    import static org.testng.Assert.assertNull;
9    import static org.testng.Assert.assertTrue;
10    import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
11   
12    import jalview.api.analysis.SimilarityParamsI;
13    import jalview.io.DataSourceType;
14    import jalview.io.FileParse;
15    import jalview.io.ScoreMatrixFile;
16    import jalview.math.Matrix;
17    import jalview.math.MatrixI;
18    import jalview.schemes.ResidueProperties;
19   
20    import java.io.IOException;
21    import java.net.MalformedURLException;
22    import java.util.Arrays;
23   
24    import org.testng.annotations.Test;
25   
26    import junit.extensions.PA;
27   
 
28    public class ScoreMatrixTest
29    {
 
30  1 toggle @Test(groups = "Functional")
31    public void testConstructor()
32    {
33    // note score matrix does not have to be symmetric (though it should be!)
34  1 float[][] scores = new float[3][];
35  1 scores[0] = new float[] { 1f, 2f, 3f };
36  1 scores[1] = new float[] { -4f, 5f, 6f };
37  1 scores[2] = new float[] { 7f, 8f, 9f };
38  1 ScoreMatrix sm = new ScoreMatrix("Test", "ABC".toCharArray(), scores);
39  1 assertFalse(sm.isSymmetric());
40  1 assertEquals(sm.getSize(), 3);
41  1 assertArrayEquals(scores, sm.getMatrix());
42  1 assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
43  1 assertEquals(sm.getPairwiseScore('b', 'c'), 6f);
44  1 assertEquals(sm.getPairwiseScore('c', 'b'), 8f);
45  1 assertEquals(sm.getMatrixIndex('c'), 2);
46  1 assertEquals(sm.getMatrixIndex(' '), -1);
47   
48    // substitution to or from unknown symbol gets minimum score
49  1 assertEquals(sm.getPairwiseScore('A', 'D'), -4f);
50  1 assertEquals(sm.getPairwiseScore('D', 'A'), -4f);
51    // unknown-to-self gets a score of 1
52  1 assertEquals(sm.getPairwiseScore('D', 'D'), 1f);
53    }
54   
 
55  1 toggle @Test(
56    groups = "Functional",
57    expectedExceptions =
58    { IllegalArgumentException.class })
59    public void testConstructor_matrixTooSmall()
60    {
61  1 float[][] scores = new float[2][];
62  1 scores[0] = new float[] { 1f, 2f };
63  1 scores[1] = new float[] { 3f, 4f };
64  1 new ScoreMatrix("Test", "ABC".toCharArray(), scores);
65    }
66   
 
67  1 toggle @Test(
68    groups = "Functional",
69    expectedExceptions =
70    { IllegalArgumentException.class })
71    public void testConstructor_matrixTooBig()
72    {
73  1 float[][] scores = new float[2][];
74  1 scores[0] = new float[] { 1f, 2f };
75  1 scores[1] = new float[] { 3f, 4f };
76  1 new ScoreMatrix("Test", "A".toCharArray(), scores);
77    }
78   
 
79  1 toggle @Test(
80    groups = "Functional",
81    expectedExceptions =
82    { IllegalArgumentException.class })
83    public void testConstructor_matrixNotSquare()
84    {
85  1 float[][] scores = new float[2][];
86  1 scores[0] = new float[] { 1f, 2f };
87  1 scores[1] = new float[] { 3f };
88  1 new ScoreMatrix("Test", "AB".toCharArray(), scores);
89    }
90   
 
91  1 toggle @Test(groups = "Functional")
92    public void testBuildSymbolIndex()
93    {
94  1 float[][] scores = new float[2][];
95  1 scores[0] = new float[] { 1f, 2f };
96  1 scores[1] = new float[] { 3f, 4f };
97  1 ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', '.' },
98    scores);
99  1 short[] index = sm.buildSymbolIndex("AX-yxYp".toCharArray());
100   
101  1 assertEquals(index.length, 128); // ASCII character set size
102   
103  1 assertEquals(index['A'], 0);
104  1 assertEquals(index['a'], 0); // lower-case mapping added
105  1 assertEquals(index['X'], 1);
106  1 assertEquals(index['-'], 2);
107  1 assertEquals(index['y'], 3); // lower-case override
108  1 assertEquals(index['x'], 4); // lower-case override
109  1 assertEquals(index['Y'], 5);
110  1 assertEquals(index['p'], 6);
111  1 assertEquals(index['P'], -1); // lower-case doesn't map upper-case
112   
113    /*
114    * check all unmapped symbols have index for unmapped
115    */
116  129 for (int c = 0; c < index.length; c++)
117    {
118  128 if (!"AaXx-. Yyp".contains(String.valueOf((char) c)))
119    {
120  118 assertEquals(index[c], -1);
121    }
122    }
123    }
124   
125    /**
126    * check that characters not in the basic ASCII set are simply ignored
127    */
 
128  1 toggle @Test(groups = "Functional")
129    public void testBuildSymbolIndex_nonAscii()
130    {
131  1 float[][] scores = new float[2][];
132  1 scores[0] = new float[] { 1f, 2f };
133  1 scores[1] = new float[] { 3f, 4f };
134  1 ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', '.' },
135    scores);
136  1 char[] weird = new char[] { 128, 245, 'P' };
137  1 short[] index = sm.buildSymbolIndex(weird);
138  1 assertEquals(index.length, 128);
139  1 assertEquals(index['P'], 2);
140  1 assertEquals(index['p'], 2);
141  129 for (int c = 0; c < index.length; c++)
142    {
143  128 if (c != 'P' && c != 'p')
144    {
145  126 assertEquals(index[c], -1);
146    }
147    }
148    }
149   
 
150  1 toggle @Test(groups = "Functional")
151    public void testGetMatrix()
152    {
153  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
154  1 float[][] m = sm.getMatrix();
155  1 assertEquals(m.length, sm.getSize());
156  1 assertEquals(m[2][4], -3f);
157    // verify a defensive copy is returned
158  1 float[][] m2 = sm.getMatrix();
159  1 assertNotSame(m, m2);
160  1 assertTrue(Arrays.deepEquals(m, m2));
161    }
162   
 
163  1 toggle @Test(groups = "Functional")
164    public void testGetMatrixIndex()
165    {
166  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
167  1 assertEquals(sm.getMatrixIndex('A'), 0);
168  1 assertEquals(sm.getMatrixIndex('R'), 1);
169  1 assertEquals(sm.getMatrixIndex('r'), 1);
170  1 assertEquals(sm.getMatrixIndex('N'), 2);
171  1 assertEquals(sm.getMatrixIndex('D'), 3);
172  1 assertEquals(sm.getMatrixIndex('X'), 22);
173  1 assertEquals(sm.getMatrixIndex('x'), 22);
174  1 assertEquals(sm.getMatrixIndex('-'), -1);
175  1 assertEquals(sm.getMatrixIndex('*'), 23);
176  1 assertEquals(sm.getMatrixIndex('.'), -1);
177  1 assertEquals(sm.getMatrixIndex(' '), -1);
178  1 assertEquals(sm.getMatrixIndex('?'), -1);
179  1 assertEquals(sm.getMatrixIndex((char) 128), -1);
180    }
181   
 
182  1 toggle @Test(groups = "Functional")
183    public void testGetSize()
184    {
185  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
186  1 assertEquals(sm.getMatrix().length, sm.getSize());
187    }
188   
 
189  1 toggle @Test(groups = "Functional")
190    public void testComputePairwiseScores()
191    {
192    /*
193    * NB score matrix expects '-' for gap
194    */
195  1 String[] seqs = new String[] { "FKL", "R-D", "QIA", "GWC" };
196  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
197   
198  1 MatrixI pairwise = sm.findSimilarities(seqs, SimilarityParams.Jalview);
199   
200    /*
201    * should be NxN where N = number of sequences
202    */
203  1 assertEquals(pairwise.height(), 4);
204  1 assertEquals(pairwise.width(), 4);
205   
206    /*
207    * should be symmetrical (because BLOSUM62 is)
208    */
209  5 for (int i = 0; i < pairwise.height(); i++)
210    {
211  10 for (int j = i + 1; j < pairwise.width(); j++)
212    {
213  6 assertEquals(pairwise.getValue(i, j), pairwise.getValue(j, i),
214    String.format("Not symmetric at [%d, %d]", i, j));
215    }
216    }
217    /*
218    * verify expected BLOSUM dot product scores
219    */
220    // F.F + K.K + L.L = 6 + 5 + 4 = 15
221  1 assertEquals(pairwise.getValue(0, 0), 15d);
222    // R.R + -.- + D.D = 5 + 1 + 6 = 12
223  1 assertEquals(pairwise.getValue(1, 1), 12d);
224    // Q.Q + I.I + A.A = 5 + 4 + 4 = 13
225  1 assertEquals(pairwise.getValue(2, 2), 13d);
226    // G.G + W.W + C.C = 6 + 11 + 9 = 26
227  1 assertEquals(pairwise.getValue(3, 3), 26d);
228    // F.R + K.- + L.D = -3 + -4 + -4 = -11
229  1 assertEquals(pairwise.getValue(0, 1), -11d);
230    // F.Q + K.I + L.A = -3 + -3 + -1 = -7
231  1 assertEquals(pairwise.getValue(0, 2), -7d);
232    // F.G + K.W + L.C = -3 + -3 + -1 = -7
233  1 assertEquals(pairwise.getValue(0, 3), -7d);
234    // R.Q + -.I + D.A = 1 + -4 + -2 = -5
235  1 assertEquals(pairwise.getValue(1, 2), -5d);
236    // R.G + -.W + D.C = -2 + -4 + -3 = -9
237  1 assertEquals(pairwise.getValue(1, 3), -9d);
238    // Q.G + I.W + A.C = -2 + -3 + 0 = -5
239  1 assertEquals(pairwise.getValue(2, 3), -5d);
240    }
241   
242    /**
243    * Test that the result of outputMatrix can be reparsed to give an identical
244    * ScoreMatrix
245    *
246    * @throws IOException
247    * @throws MalformedURLException
248    */
 
249  1 toggle @Test(groups = "Functional")
250    public void testOutputMatrix_roundTrip()
251    throws MalformedURLException, IOException
252    {
253  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
254  1 String output = sm.outputMatrix(false);
255  1 FileParse fp = new FileParse(output, DataSourceType.PASTE);
256  1 ScoreMatrixFile parser = new ScoreMatrixFile(fp);
257  1 ScoreMatrix sm2 = parser.parseMatrix();
258  1 assertNotNull(sm2);
259  1 assertTrue(sm2.equals(sm));
260    }
261   
 
262  1 toggle @Test(groups = "Functional")
263    public void testEqualsAndHashCode()
264    {
265  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
266  1 ScoreMatrix sm2 = new ScoreMatrix(sm.getName(),
267    sm.getSymbols().toCharArray(), sm.getMatrix());
268  1 assertTrue(sm.equals(sm2));
269  1 assertEquals(sm.hashCode(), sm2.hashCode());
270   
271  1 sm2 = ScoreModels.getInstance().getPam250();
272  1 assertFalse(sm.equals(sm2));
273  1 assertNotEquals(sm.hashCode(), sm2.hashCode());
274   
275  1 assertFalse(sm.equals("hello"));
276    }
277   
278    /**
279    * Tests for scoring options where the longer length of two sequences is used
280    */
 
281  1 toggle @Test(groups = "Functional")
282    public void testcomputeSimilarity_matchLongestSequence()
283    {
284    /*
285    * ScoreMatrix expects '-' for gaps
286    */
287  1 String s1 = "FR-K-S";
288  1 String s2 = "FS--L";
289  1 ScoreMatrix blosum = ScoreModels.getInstance().getBlosum62();
290   
291    /*
292    * score gap-gap and gap-char
293    * shorter sequence treated as if with trailing gaps
294    * score = F^F + R^S + -^- + K^- + -^L + S^-
295    * = 6 + -1 + 1 + -4 + -4 + -4 = -6
296    */
297  1 SimilarityParamsI params = new SimilarityParams(true, true, true,
298    false);
299  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -6d);
300    // matchGap (arg2) is ignored:
301  1 params = new SimilarityParams(true, false, true, false);
302  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -6d);
303   
304    /*
305    * score gap-char but not gap-gap
306    * score = F^F + R^S + 0 + K^- + -^L + S^-
307    * = 6 + -1 + 0 + -4 + -4 + -4 = -7
308    */
309  1 params = new SimilarityParams(false, true, true, false);
310  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -7d);
311    // matchGap (arg2) is ignored:
312  1 params = new SimilarityParams(false, false, true, false);
313  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -7d);
314   
315    /*
316    * score gap-gap but not gap-char
317    * score = F^F + R^S + -^- + 0 + 0 + 0
318    * = 6 + -1 + 1 = 6
319    */
320  1 params = new SimilarityParams(true, false, false, false);
321  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
322    // matchGap (arg2) is ignored:
323  1 params = new SimilarityParams(true, true, false, false);
324  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
325   
326    /*
327    * score neither gap-gap nor gap-char
328    * score = F^F + R^S + 0 + 0 + 0 + 0
329    * = 6 + -1 = 5
330    */
331  1 params = new SimilarityParams(false, false, false, false);
332  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
333    // matchGap (arg2) is ignored:
334  1 params = new SimilarityParams(false, true, false, false);
335  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
336    }
337   
338    /**
339    * Tests for scoring options where only the shorter length of two sequences is
340    * used
341    */
 
342  1 toggle @Test(groups = "Functional")
343    public void testcomputeSimilarity_matchShortestSequence()
344    {
345    /*
346    * ScoreMatrix expects '-' for gaps
347    */
348  1 String s1 = "FR-K-S";
349  1 String s2 = "FS--L";
350  1 ScoreMatrix blosum = ScoreModels.getInstance().getBlosum62();
351   
352    /*
353    * score gap-gap and gap-char
354    * match shorter sequence only
355    * score = F^F + R^S + -^- + K^- + -^L
356    * = 6 + -1 + 1 + -4 + -4 = -2
357    */
358  1 SimilarityParamsI params = new SimilarityParams(true, true, true, true);
359  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -2d);
360    // matchGap (arg2) is ignored:
361  1 params = new SimilarityParams(true, false, true, true);
362  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -2d);
363   
364    /*
365    * score gap-char but not gap-gap
366    * score = F^F + R^S + 0 + K^- + -^L
367    * = 6 + -1 + 0 + -4 + -4 = -3
368    */
369  1 params = new SimilarityParams(false, true, true, true);
370  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -3d);
371    // matchGap (arg2) is ignored:
372  1 params = new SimilarityParams(false, false, true, true);
373  1 assertEquals(blosum.computeSimilarity(s1, s2, params), -3d);
374   
375    /*
376    * score gap-gap but not gap-char
377    * score = F^F + R^S + -^- + 0 + 0
378    * = 6 + -1 + 1 = 6
379    */
380  1 params = new SimilarityParams(true, false, false, true);
381  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
382    // matchGap (arg2) is ignored:
383  1 params = new SimilarityParams(true, true, false, true);
384  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
385   
386    /*
387    * score neither gap-gap nor gap-char
388    * score = F^F + R^S + 0 + 0 + 0
389    * = 6 + -1 = 5
390    */
391  1 params = new SimilarityParams(false, false, false, true);
392  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
393    // matchGap (arg2) is ignored:
394  1 params = new SimilarityParams(false, true, false, true);
395  1 assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
396    }
397   
 
398  1 toggle @Test(groups = "Functional")
399    public void testSymmetric()
400    {
401  1 verifySymmetric(ScoreModels.getInstance().getBlosum62());
402  1 verifySymmetric(ScoreModels.getInstance().getPam250());
403  1 verifySymmetric(ScoreModels.getInstance().getDefaultModel(false)); // dna
404    }
405   
406    /**
407    * A helper method that inspects a loaded matrix and reports any asymmetry as
408    * a test failure
409    *
410    * @param sm
411    */
 
412  3 toggle private void verifySymmetric(ScoreMatrix sm)
413    {
414  3 float[][] m = sm.getMatrix();
415  3 int rows = m.length;
416  62 for (int row = 0; row < rows; row++)
417    {
418  59 assertEquals(m[row].length, rows);
419  1332 for (int col = 0; col < rows; col++)
420    {
421  1273 assertEquals(m[row][col], m[col][row],
422    String.format("%s [%s, %s]", sm.getName(),
423    ResidueProperties.aa[row],
424    ResidueProperties.aa[col]));
425    }
426    }
427    }
428   
429    /**
430    * A test that just asserts the expected values in the Blosum62 score matrix
431    */
 
432  1 toggle @Test(groups = "Functional")
433    public void testBlosum62_values()
434    {
435  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
436   
437  1 assertTrue(sm.isProtein());
438  1 assertFalse(sm.isDNA());
439  1 assertNull(sm.getDescription());
440   
441    /*
442    * verify expected scores against ARNDCQEGHILKMFPSTWYVBZX
443    * scraped from https://www.ncbi.nlm.nih.gov/Class/FieldGuide/BLOSUM62.txt
444    */
445  1 verifyValues(sm, 'A',
446    new float[]
447    { 4, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0,
448    -3, -2, 0, -2, -1, 0 });
449  1 verifyValues(sm, 'R',
450    new float[]
451    { -1, 5, 0, -2, -3, 1, 0, -2, 0, -3, -2, 2, -1, -3, -2, -1, -1,
452    -3, -2, -3, -1, 0, -1 });
453  1 verifyValues(sm, 'N',
454    new float[]
455    { -2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3, 0, -2, -3, -2, 1, 0, -4,
456    -2, -3, 3, 0, -1 });
457  1 verifyValues(sm, 'D',
458    new float[]
459    { -2, -2, 1, 6, -3, 0, 2, -1, -1, -3, -4, -1, -3, -3, -1, 0, -1,
460    -4, -3, -3, 4, 1, -1 });
461  1 verifyValues(sm, 'C',
462    new float[]
463    { 0, -3, -3, -3, 9, -3, -4, -3, -3, -1, -1, -3, -1, -2, -3, -1,
464    -1, -2, -2, -1, -3, -3, -2 });
465  1 verifyValues(sm, 'Q',
466    new float[]
467    { -1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2, 1, 0, -3, -1, 0, -1, -2,
468    -1, -2, 0, 3, -1 });
469  1 verifyValues(sm, 'E',
470    new float[]
471    { -1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3, 1, -2, -3, -1, 0, -1,
472    -3, -2, -2, 1, 4, -1 });
473  1 verifyValues(sm, 'G',
474    new float[]
475    { 0, -2, 0, -1, -3, -2, -2, 6, -2, -4, -4, -2, -3, -3, -2, 0,
476    -2, -2, -3, -3, -1, -2, -1 });
477  1 verifyValues(sm, 'H',
478    new float[]
479    { -2, 0, 1, -1, -3, 0, 0, -2, 8, -3, -3, -1, -2, -1, -2, -1, -2,
480    -2, 2, -3, 0, 0, -1 });
481  1 verifyValues(sm, 'I',
482    new float[]
483    { -1, -3, -3, -3, -1, -3, -3, -4, -3, 4, 2, -3, 1, 0, -3, -2,
484    -1, -3, -1, 3, -3, -3, -1 });
485  1 verifyValues(sm, 'L',
486    new float[]
487    { -1, -2, -3, -4, -1, -2, -3, -4, -3, 2, 4, -2, 2, 0, -3, -2,
488    -1, -2, -1, 1, -4, -3, -1 });
489  1 verifyValues(sm, 'K',
490    new float[]
491    { -1, 2, 0, -1, -3, 1, 1, -2, -1, -3, -2, 5, -1, -3, -1, 0, -1,
492    -3, -2, -2, 0, 1, -1 });
493  1 verifyValues(sm, 'M',
494    new float[]
495    { -1, -1, -2, -3, -1, 0, -2, -3, -2, 1, 2, -1, 5, 0, -2, -1, -1,
496    -1, -1, 1, -3, -1, -1 });
497  1 verifyValues(sm, 'F',
498    new float[]
499    { -2, -3, -3, -3, -2, -3, -3, -3, -1, 0, 0, -3, 0, 6, -4, -2,
500    -2, 1, 3, -1, -3, -3, -1 });
501  1 verifyValues(sm, 'P',
502    new float[]
503    { -1, -2, -2, -1, -3, -1, -1, -2, -2, -3, -3, -1, -2, -4, 7, -1,
504    -1, -4, -3, -2, -2, -1, -2 });
505  1 verifyValues(sm, 'S',
506    new float[]
507    { 1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2, 0, -1, -2, -1, 4, 1, -3,
508    -2, -2, 0, 0, 0 });
509  1 verifyValues(sm, 'T',
510    new float[]
511    { 0, -1, 0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1, -2, -1, 1,
512    5, -2, -2, 0, -1, -1, 0 });
513  1 verifyValues(sm, 'W',
514    new float[]
515    { -3, -3, -4, -4, -2, -2, -3, -2, -2, -3, -2, -3, -1, 1, -4, -3,
516    -2, 11, 2, -3, -4, -3, -2 });
517  1 verifyValues(sm, 'Y',
518    new float[]
519    { -2, -2, -2, -3, -2, -1, -2, -3, 2, -1, -1, -2, -1, 3, -3, -2,
520    -2, 2, 7, -1, -3, -2, -1 });
521  1 verifyValues(sm, 'V',
522    new float[]
523    { 0, -3, -3, -3, -1, -2, -2, -3, -3, 3, 1, -2, 1, -1, -2, -2, 0,
524    -3, -1, 4, -3, -2, -1 });
525  1 verifyValues(sm, 'B',
526    new float[]
527    { -2, -1, 3, 4, -3, 0, 1, -1, 0, -3, -4, 0, -3, -3, -2, 0, -1,
528    -4, -3, -3, 4, 1, -1 });
529  1 verifyValues(sm, 'Z',
530    new float[]
531    { -1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3, 1, -1, -3, -1, 0, -1,
532    -3, -2, -2, 1, 4, -1 });
533  1 verifyValues(sm, 'X',
534    new float[]
535    { 0, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 0,
536    0, -2, -1, -1, -1, -1, -1 });
537    }
538   
539    /**
540    * Helper method to check pairwise scores for one residue
541    *
542    * @param sm
543    * @param res
544    * @param expected
545    * score values against 'res', in ResidueProperties.aaIndex order
546    */
 
547  23 toggle private void verifyValues(ScoreMatrix sm, char res, float[] expected)
548    {
549  552 for (int j = 0; j < expected.length; j++)
550    {
551  529 char c2 = ResidueProperties.aa[j].charAt(0);
552  529 assertEquals(sm.getPairwiseScore(res, c2), expected[j],
553    String.format("%s->%s", res, c2));
554    }
555    }
556   
 
557  1 toggle @Test(groups = "Functional")
558    public void testConstructor_gapDash()
559    {
560  1 float[][] scores = new float[2][];
561  1 scores[0] = new float[] { 1f, 2f };
562  1 scores[1] = new float[] { 4f, 5f };
563  1 ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', '-' },
564    scores);
565  1 assertEquals(sm.getSize(), 2);
566  1 assertArrayEquals(scores, sm.getMatrix());
567  1 assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
568  1 assertEquals(sm.getPairwiseScore('A', 'A'), 1f);
569  1 assertEquals(sm.getPairwiseScore('a', '-'), 2f);
570  1 assertEquals(sm.getPairwiseScore('-', 'A'), 4f);
571  1 assertEquals(sm.getMatrixIndex('a'), 0);
572  1 assertEquals(sm.getMatrixIndex('A'), 0);
573  1 assertEquals(sm.getMatrixIndex('-'), 1);
574  1 assertEquals(sm.getMatrixIndex(' '), -1);
575  1 assertEquals(sm.getMatrixIndex('.'), -1);
576    }
577   
 
578  1 toggle @Test(groups = "Functional")
579    public void testGetPairwiseScore()
580    {
581  1 float[][] scores = new float[2][];
582  1 scores[0] = new float[] { 1f, 2f };
583  1 scores[1] = new float[] { -4f, 5f };
584  1 ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', 'B' },
585    scores);
586  1 assertEquals(sm.getPairwiseScore('A', 'A'), 1f);
587  1 assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
588  1 assertEquals(sm.getPairwiseScore('A', 'B'), 2f);
589  1 assertEquals(sm.getPairwiseScore('b', 'a'), -4f);
590  1 assertEquals(sm.getPairwiseScore('B', 'b'), 5f);
591   
592    /*
593    * unknown symbols currently score minimum score
594    * or 1 for identity with self
595    */
596  1 assertEquals(sm.getPairwiseScore('A', '-'), -4f);
597  1 assertEquals(sm.getPairwiseScore('-', 'A'), -4f);
598  1 assertEquals(sm.getPairwiseScore('-', '-'), 1f);
599  1 assertEquals(sm.getPairwiseScore('Q', 'W'), -4f);
600  1 assertEquals(sm.getPairwiseScore('Q', 'Q'), 1f);
601   
602    /*
603    * symbols not in basic ASCII set score zero
604    */
605  1 char c = (char) 200;
606  1 assertEquals(sm.getPairwiseScore('Q', c), 0f);
607  1 assertEquals(sm.getPairwiseScore(c, 'Q'), 0f);
608    }
609   
 
610  1 toggle @Test(groups = "Functional")
611    public void testGetMinimumScore()
612    {
613  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
614  1 assertEquals(sm.getMinimumScore(), -4f);
615    }
616   
 
617  1 toggle @Test(groups = "Functional")
618    public void testGetMaximumScore()
619    {
620  1 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
621  1 assertEquals(sm.getMaximumScore(), 11f);
622    }
623   
 
624  1 toggle @Test(groups = "Functional")
625    public void testOutputMatrix_html()
626    {
627  1 float[][] scores = new float[2][];
628  1 scores[0] = new float[] { 1f, 2f };
629  1 scores[1] = new float[] { 4f, -5.3E-10f };
630  1 ScoreMatrix sm = new ScoreMatrix("Test", "AB".toCharArray(), scores);
631  1 String html = sm.outputMatrix(true);
632  1 String expected = "<table border=\"1\"><tr><th></th><th>&nbsp;A&nbsp;</th><th>&nbsp;B&nbsp;</th></tr>\n"
633    + "<tr><td>A</td><td>1.0</td><td>2.0</td></tr>\n"
634    + "<tr><td>B</td><td>4.0</td><td>-5.3E-10</td></tr>\n"
635    + "</table>";
636  1 assertEquals(html, expected);
637    }
638   
 
639  1 toggle @Test(groups = "Functional")
640    public void testIsSymmetric()
641    {
642  1 double delta = 0.0001d;
643  1 float[][] scores = new float[][] { { 1f, -2f }, { -2f, 3f } };
644  1 ScoreMatrix sm = new ScoreMatrix("Test", "AB".toCharArray(), scores);
645  1 assertTrue(sm.isSymmetric());
646   
647    /*
648    * verify that with a symmetric score matrix,
649    * pairwise similarity matrix is also symmetric
650    * seq1.seq1 = 5*A.A + 3*B.B = 5+9 = 14
651    * seq1.seq2 = 3*A.A + 2*A.B + B.A + 2*B.B = 3 + -4 + -2 + 6 = 3
652    * seq2.seq1 = 3*A.A + A.B + 2*B.A + 2*B.B = 3 + -2 + -4 + 6 = 3
653    * seq2.seq2 = 4*A.A + 4*B.B = 4 + 12 = 16
654    */
655  1 SimilarityParamsI params = new SimilarityParams(true, true, true,
656    false);
657  1 String seq1 = "AAABBBAA";
658  1 String seq2 = "AABBABBA";
659  1 String[] seqs1 = new String[] { seq1, seq2 };
660  1 MatrixI res1 = sm.findSimilarities(seqs1, params);
661  1 assertTrue(
662    res1.equals(new Matrix(new double[][]
663    { { 14d, 3d }, { 3d, 16d } }), delta));
664   
665    /*
666    * order of sequences affects diagonal, but not off-diagonal values
667    * [0, 0] is now seq2.seq2, [1, 1] is seq1.seq1
668    * [0, 1] is now seq2.seq1 = seq1.seq2 by symmetry
669    */
670  1 String[] seqs2 = new String[] { seq2, seq1 };
671  1 MatrixI res2 = sm.findSimilarities(seqs2, params);
672  1 assertFalse(res1.equals(res2));
673  1 assertTrue(res2.equals(new Matrix(new double[][]
674    { { 16d, 3d }, { 3d, 14d } }), delta));
675   
676    /*
677    * now make the score matrix asymmetric
678    * seq1.seq1 = 5*A.A + 3*B.B = 5+9 = 14
679    * seq1.seq2 = 3*A.A + 2*A.B + B.A + 2*B.B = 3 + -4 + 2 + 6 = 7
680    * seq2.seq1 = 3*A.A + A.B + 2*B.A + 2*B.B = 3 + -2 + 4 + 6 = 11
681    * seq2.seq2 = 4*A.A + 4*B.B = 4 + 12 = 16
682    */
683  1 scores = new float[][] { { 1f, -2f }, { 2f, 3f } };
684  1 sm = new ScoreMatrix("Test", "AB".toCharArray(), scores);
685  1 assertFalse(sm.isSymmetric()); // [0, 1] != [1, 0]
686  1 res1 = sm.findSimilarities(seqs1, params);
687  1 assertTrue(res1.equals(new Matrix(new double[][]
688    { { 14d, 7d }, { 11d, 16d } }), delta));
689   
690    /*
691    * reverse order of sequences
692    * - reverses order of main diagonal
693    * - reflects off-diagonal values
694    */
695  1 res2 = sm.findSimilarities(seqs2, params);
696  1 assertFalse(res1.equals(res2));
697  1 assertTrue(
698    res2.equals(new Matrix(new double[][]
699    { { 16d, 11d }, { 7d, 14d } }), delta));
700   
701    /*
702    * verify that forcing an asymmetric matrix to use
703    * symmetric calculation gives a different (wrong) result
704    */
705  1 PA.setValue(sm, "symmetric", true);
706  1 assertTrue(sm.isSymmetric()); // it's not true!
707  1 res2 = sm.findSimilarities(seqs1, params);
708  1 assertFalse(res1.equals(res2, delta));
709    }
710    }