1 package jalview.analysis.scoremodels;
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertNotNull;
5 import static org.testng.Assert.assertTrue;
6 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
8 import jalview.io.DataSourceType;
9 import jalview.io.FileParse;
10 import jalview.io.ScoreMatrixFile;
11 import jalview.math.MatrixI;
13 import java.io.IOException;
14 import java.net.MalformedURLException;
16 import org.testng.annotations.Test;
18 public class ScoreMatrixTest
20 @Test(groups = "Functional")
21 public void testConstructor()
23 // note score matrix does not have to be symmetric (though it should be!)
24 float[][] scores = new float[3][];
25 scores[0] = new float[] { 1f, 2f, 3f };
26 scores[1] = new float[] { 4f, 5f, 6f };
27 scores[2] = new float[] { 7f, 8f, 9f };
28 ScoreMatrix sm = new ScoreMatrix("Test", "ABC".toCharArray(), scores);
29 assertEquals(sm.getSize(), 3);
30 assertArrayEquals(scores, sm.getMatrix());
31 assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
32 assertEquals(sm.getPairwiseScore('b', 'c'), 6f);
33 assertEquals(sm.getPairwiseScore('c', 'b'), 8f);
34 assertEquals(sm.getPairwiseScore('A', 'D'), 0f);
35 assertEquals(sm.getMatrixIndex('c'), 2);
36 assertEquals(sm.getMatrixIndex(' '), -1);
40 groups = "Functional",
41 expectedExceptions = { IllegalArgumentException.class })
42 public void testConstructor_matrixTooSmall()
44 float[][] scores = new float[2][];
45 scores[0] = new float[] { 1f, 2f };
46 scores[1] = new float[] { 3f, 4f };
47 new ScoreMatrix("Test", "ABC".toCharArray(), scores);
51 groups = "Functional",
52 expectedExceptions = { IllegalArgumentException.class })
53 public void testConstructor_matrixTooBig()
55 float[][] scores = new float[2][];
56 scores[0] = new float[] { 1f, 2f };
57 scores[1] = new float[] { 3f, 4f };
58 new ScoreMatrix("Test", "A".toCharArray(), scores);
62 groups = "Functional",
63 expectedExceptions = { IllegalArgumentException.class })
64 public void testConstructor_matrixNotSquare()
66 float[][] scores = new float[2][];
67 scores[0] = new float[] { 1f, 2f };
68 scores[1] = new float[] { 3f };
69 new ScoreMatrix("Test", "AB".toCharArray(), scores);
72 @Test(groups = "Functional")
73 public void testBuildSymbolIndex()
75 short[] index = ScoreMatrix.buildSymbolIndex("AX-. yxYp".toCharArray());
77 assertEquals(index.length, 128); // ASCII character set size
79 assertEquals(index['A'], 0);
80 assertEquals(index['a'], 0); // lower-case mapping added
81 assertEquals(index['X'], 1);
82 assertEquals(index['-'], 2);
83 assertEquals(index['.'], 3);
84 assertEquals(index[' '], 4);
85 assertEquals(index['y'], 5); // lower-case override
86 assertEquals(index['x'], 6); // lower-case override
87 assertEquals(index['Y'], 7);
88 assertEquals(index['p'], 8);
89 assertEquals(index['P'], -1); // lower-case doesn't map upper-case
92 * check all unmapped symbols have index for unmapped
94 for (int c = 0; c < index.length; c++)
96 if (!"AaXx-. Yyp".contains(String.valueOf((char) c)))
98 assertEquals(index[c], -1);
104 * check that characters not in the basic ASCII set are simply ignored
106 @Test(groups = "Functional")
107 public void testBuildSymbolIndex_nonAscii()
109 char[] weird = new char[] { 128, 245, 'P' };
110 short[] index = ScoreMatrix.buildSymbolIndex(weird);
111 assertEquals(index.length, 128);
112 assertEquals(index['P'], 2);
113 assertEquals(index['p'], 2);
114 for (int c = 0; c < index.length; c++)
116 if (c != 'P' && c != 'p')
118 assertEquals(index[c], -1);
123 @Test(groups = "Functional")
124 public void testGetMatrixIndex()
126 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
127 assertEquals(sm.getMatrixIndex('A'), 0);
128 assertEquals(sm.getMatrixIndex('R'), 1);
129 assertEquals(sm.getMatrixIndex('r'), 1);
130 assertEquals(sm.getMatrixIndex('N'), 2);
131 assertEquals(sm.getMatrixIndex('D'), 3);
132 assertEquals(sm.getMatrixIndex('X'), 22);
133 assertEquals(sm.getMatrixIndex('x'), 22);
134 assertEquals(sm.getMatrixIndex(' '), 23);
135 assertEquals(sm.getMatrixIndex('*'), 24);
136 assertEquals(sm.getMatrixIndex('.'), -1);
137 assertEquals(sm.getMatrixIndex('-'), -1);
138 assertEquals(sm.getMatrixIndex('?'), -1);
139 assertEquals(sm.getMatrixIndex((char) 128), -1);
142 @Test(groups = "Functional")
143 public void testGetSize()
145 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
146 assertEquals(sm.getMatrix().length, sm.getSize());
149 @Test(groups = "Functional")
150 public void testComputePairwiseScores()
153 * NB score matrix assumes space for gap - Jalview converts
154 * space to gap before computing PCA or Tree
156 String[] seqs = new String[] { "FKL", "R D", "QIA", "GWC" };
157 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
159 MatrixI pairwise = sm.computePairwiseScores(seqs);
162 * should be NxN where N = number of sequences
164 assertEquals(pairwise.height(), 4);
165 assertEquals(pairwise.width(), 4);
168 * should be symmetrical (because BLOSUM62 is)
170 for (int i = 0; i < pairwise.height(); i++)
172 for (int j = i + 1; j < pairwise.width(); j++)
174 assertEquals(pairwise.getValue(i, j), pairwise.getValue(j, i),
175 String.format("Not symmetric at [%d, %d]", i, j));
179 * verify expected BLOSUM dot product scores
181 // F.F + K.K + L.L = 6 + 5 + 4 = 15
182 assertEquals(pairwise.getValue(0, 0), 15d);
183 // R.R + -.- + D.D = 5 + 1 + 6 = 12
184 assertEquals(pairwise.getValue(1, 1), 12d);
185 // Q.Q + I.I + A.A = 5 + 4 + 4 = 13
186 assertEquals(pairwise.getValue(2, 2), 13d);
187 // G.G + W.W + C.C = 6 + 11 + 9 = 26
188 assertEquals(pairwise.getValue(3, 3), 26d);
189 // F.R + K.- + L.D = -3 + -4 + -4 = -11
190 assertEquals(pairwise.getValue(0, 1), -11d);
191 // F.Q + K.I + L.A = -3 + -3 + -1 = -7
192 assertEquals(pairwise.getValue(0, 2), -7d);
193 // F.G + K.W + L.C = -3 + -3 + -1 = -7
194 assertEquals(pairwise.getValue(0, 3), -7d);
195 // R.Q + -.I + D.A = 1 + -4 + -2 = -5
196 assertEquals(pairwise.getValue(1, 2), -5d);
197 // R.G + -.W + D.C = -2 + -4 + -3 = -9
198 assertEquals(pairwise.getValue(1, 3), -9d);
199 // Q.G + I.W + A.C = -2 + -3 + 0 = -5
200 assertEquals(pairwise.getValue(2, 3), -5d);
204 * Test that the result of outputMatrix can be reparsed to give an identical
207 * @throws IOException
208 * @throws MalformedURLException
210 @Test(groups = "Functional")
211 public void testOutputMatrix_roundTrip() throws MalformedURLException,
214 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
215 String output = sm.outputMatrix(false);
216 FileParse fp = new FileParse(output, DataSourceType.PASTE);
217 ScoreMatrixFile parser = new ScoreMatrixFile(fp);
218 ScoreMatrix sm2 = parser.parseMatrix();
220 assertTrue(sm2.equals(sm));