Clover icon

Coverage Report

  1. Project Clover database Wed Nov 13 2024 16:21:17 GMT
  2. Package jalview.analysis.scoremodels

File ScoreMatrixTest.java

 

Code metrics

18
260
24
1
732
498
34
0.13
10.83
24
1.42

Classes

Class Line # Actions
ScoreMatrixTest 48 260 34
1.0100%
 

Contributing tests

This file is covered by 22 tests. .

Source view

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