JAL-2397 PCA gap cost uses last column of score matrix
[jalview.git] / test / jalview / schemes / ScoreMatrixTest.java
1 package jalview.schemes;
2
3 import static org.testng.Assert.assertEquals;
4
5 import jalview.math.MatrixI;
6
7 import org.testng.annotations.Test;
8
9 public class ScoreMatrixTest
10 {
11   @Test(groups = "Functional")
12   public void testSymmetric()
13   {
14     verifySymmetric(ResidueProperties.getScoreMatrix("BLOSUM62"));
15     verifySymmetric(ResidueProperties.getScoreMatrix("PAM250"));
16     verifySymmetric(ResidueProperties.getScoreMatrix("DNA"));
17   }
18
19   private void verifySymmetric(ScoreMatrix sm)
20   {
21     int[][] m = sm.getMatrix();
22     int rows = m.length;
23     for (int row = 0; row < rows; row++)
24     {
25       assertEquals(m[row].length, rows);
26       for (int col = 0; col < rows; col++)
27       {
28         assertEquals(m[row][col], m[col][row], String.format("%s [%s, %s]",
29                 sm.getName(), ResidueProperties.aa[row],
30                 ResidueProperties.aa[col]));
31       }
32     }
33
34     /*
35      * also check the score matrix is sized for 
36      * the number of symbols scored, plus gap
37      */
38     assertEquals(rows, (sm.isDNA() ? ResidueProperties.maxNucleotideIndex
39             : ResidueProperties.maxProteinIndex) + 1);
40   }
41
42   /**
43    * A test that just asserts the expected values in the Blosum62 score matrix
44    */
45   @Test(groups = "Functional")
46   public void testBlosum62_values()
47   {
48     ScoreMatrix sm = ResidueProperties.getScoreMatrix("BLOSUM62");
49
50     /*
51      * verify expected scores against ARNDCQEGHILKMFPSTWYVBZX
52      * scraped from https://www.ncbi.nlm.nih.gov/Class/FieldGuide/BLOSUM62.txt
53      */
54     verifyValues(sm, 'A', new int[] { 4, -1, -2, -2, 0, -1, -1, 0, -2, -1,
55         -1, -1, -1, -2, -1, 1, 0, -3, -2, 0, -2, -1, 0 });
56     verifyValues(sm, 'R', new int[] { -1, 5, 0, -2, -3, 1, 0, -2, 0, -3,
57         -2, 2, -1, -3, -2, -1, -1, -3, -2, -3, -1, 0, -1 });
58     verifyValues(sm, 'N', new int[] { -2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3,
59         0, -2, -3, -2, 1, 0, -4, -2, -3, 3, 0, -1 });
60     verifyValues(sm, 'D', new int[] { -2, -2, 1, 6, -3, 0, 2, -1, -1, -3,
61         -4, -1, -3, -3, -1, 0, -1, -4, -3, -3, 4, 1, -1 });
62     verifyValues(sm, 'C', new int[] { 0, -3, -3, -3, 9, -3, -4, -3, -3, -1,
63         -1, -3, -1, -2, -3, -1, -1, -2, -2, -1, -3, -3, -2 });
64     verifyValues(sm, 'Q', new int[] { -1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2,
65         1, 0, -3, -1, 0, -1, -2, -1, -2, 0, 3, -1 });
66     verifyValues(sm, 'E', new int[] { -1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3,
67         1, -2, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1 });
68     verifyValues(sm, 'G', new int[] { 0, -2, 0, -1, -3, -2, -2, 6, -2, -4,
69         -4, -2, -3, -3, -2, 0, -2, -2, -3, -3, -1, -2, -1 });
70     verifyValues(sm, 'H', new int[] { -2, 0, 1, -1, -3, 0, 0, -2, 8, -3,
71         -3, -1, -2, -1, -2, -1, -2, -2, 2, -3, 0, 0, -1 });
72     verifyValues(sm, 'I', new int[] { -1, -3, -3, -3, -1, -3, -3, -4, -3,
73         4, 2, -3, 1, 0, -3, -2, -1, -3, -1, 3, -3, -3, -1 });
74     verifyValues(sm, 'L', new int[] { -1, -2, -3, -4, -1, -2, -3, -4, -3,
75         2, 4, -2, 2, 0, -3, -2, -1, -2, -1, 1, -4, -3, -1 });
76     verifyValues(sm, 'K', new int[] { -1, 2, 0, -1, -3, 1, 1, -2, -1, -3,
77         -2, 5, -1, -3, -1, 0, -1, -3, -2, -2, 0, 1, -1 });
78     verifyValues(sm, 'M', new int[] { -1, -1, -2, -3, -1, 0, -2, -3, -2, 1,
79         2, -1, 5, 0, -2, -1, -1, -1, -1, 1, -3, -1, -1 });
80     verifyValues(sm, 'F', new int[] { -2, -3, -3, -3, -2, -3, -3, -3, -1,
81         0, 0, -3, 0, 6, -4, -2, -2, 1, 3, -1, -3, -3, -1 });
82     verifyValues(sm, 'P', new int[] { -1, -2, -2, -1, -3, -1, -1, -2, -2,
83         -3, -3, -1, -2, -4, 7, -1, -1, -4, -3, -2, -2, -1, -2 });
84     verifyValues(sm, 'S', new int[] { 1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2,
85         0, -1, -2, -1, 4, 1, -3, -2, -2, 0, 0, 0 });
86     verifyValues(sm, 'T', new int[] { 0, -1, 0, -1, -1, -1, -1, -2, -2, -1,
87         -1, -1, -1, -2, -1, 1, 5, -2, -2, 0, -1, -1, 0 });
88     verifyValues(sm, 'W', new int[] { -3, -3, -4, -4, -2, -2, -3, -2, -2,
89         -3, -2, -3, -1, 1, -4, -3, -2, 11, 2, -3, -4, -3, -2 });
90     verifyValues(sm, 'Y', new int[] { -2, -2, -2, -3, -2, -1, -2, -3, 2,
91         -1, -1, -2, -1, 3, -3, -2, -2, 2, 7, -1, -3, -2, -1 });
92     verifyValues(sm, 'V', new int[] { 0, -3, -3, -3, -1, -2, -2, -3, -3, 3,
93         1, -2, 1, -1, -2, -2, 0, -3, -1, 4, -3, -2, -1 });
94     verifyValues(sm, 'B', new int[] { -2, -1, 3, 4, -3, 0, 1, -1, 0, -3,
95         -4, 0, -3, -3, -2, 0, -1, -4, -3, -3, 4, 1, -1 });
96     verifyValues(sm, 'Z', new int[] { -1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3,
97         1, -1, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1 });
98     verifyValues(sm, 'X', new int[] { 0, -1, -1, -1, -2, -1, -1, -1, -1,
99         -1, -1, -1, -1, -1, -2, 0, 0, -2, -1, -1, -1, -1, -1 });
100   }
101   /**
102    * Helper method to check pairwise scores for one residue
103    * 
104    * @param sm
105    * @param res
106    * @param expected
107    *          score values against 'res', in ResidueProperties.aaIndex order
108    */
109   private void verifyValues(ScoreMatrix sm, char res, int[] expected)
110   {
111     for (int j = 0; j < expected.length; j++)
112     {
113       char c2 = ResidueProperties.aa[j].charAt(0);
114       assertEquals(sm.getPairwiseScore(res, c2), expected[j],
115               String.format("%s->%s", res, c2));
116     }
117   }
118
119   @Test(groups = "Functional")
120   public void testComputePairwiseScores()
121   {
122     String[] seqs = new String[] { "FKL", "R-D", "QIA", "GWC" };
123     ScoreMatrix sm = ResidueProperties.getScoreMatrix("BLOSUM62");
124   
125     MatrixI pairwise = sm.computePairwiseScores(seqs);
126   
127     /*
128      * should be NxN where N = number of sequences
129      */
130     assertEquals(pairwise.height(), 4);
131     assertEquals(pairwise.width(), 4);
132   
133     /*
134      * should be symmetrical (because BLOSUM62 is)
135      */
136     for (int i = 0; i < pairwise.height(); i++)
137     {
138       for (int j = 0; j < pairwise.width(); j++)
139       {
140         assertEquals(pairwise.getValue(i, j), pairwise.getValue(j, i),
141                 "Not symmetric");
142       }
143     }
144     /*
145      * verify expected BLOSUM dot product scores
146      */
147     // F.F + K.K + L.L = 6 + 5 + 4 = 15
148     assertEquals(pairwise.getValue(0, 0), 15d);
149     // R.R + -.- + D.D = 5 + 1 + 6 = 12
150     assertEquals(pairwise.getValue(1, 1), 12d);
151     // Q.Q + I.I + A.A = 5 + 4 + 4 = 13
152     assertEquals(pairwise.getValue(2, 2), 13d);
153     // G.G + W.W + C.C = 6 + 11 + 9 = 26
154     assertEquals(pairwise.getValue(3, 3), 26d);
155     // F.R + K.- + L.D = -3 + -4 + -4 = -11
156     assertEquals(pairwise.getValue(0, 1), -11d);
157     // F.Q + K.I + L.A = -3 + -3 + -1 = -7
158     assertEquals(pairwise.getValue(0, 2), -7d);
159     // F.G + K.W + L.C = -3 + -3 + -1 = -7
160     assertEquals(pairwise.getValue(0, 3), -7d);
161     // R.Q + -.I + D.A = 1 + -4 + -2 = -5
162     assertEquals(pairwise.getValue(1, 2), -5d);
163     // R.G + -.W + D.C = -2 + -4 + -3 = -9
164     assertEquals(pairwise.getValue(1, 3), -9d);
165     // Q.G + I.W + A.C = -2 + -3 + 0 = -5
166     assertEquals(pairwise.getValue(2, 3), -5d);
167   }
168 }