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.assertNotSame;
6 import static org.testng.Assert.assertTrue;
7 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
9 import jalview.io.DataSourceType;
10 import jalview.io.FileParse;
11 import jalview.io.ScoreMatrixFile;
12 import jalview.math.MatrixI;
14 import java.io.IOException;
15 import java.net.MalformedURLException;
16 import java.util.Arrays;
18 import org.testng.annotations.Test;
20 public class ScoreMatrixTest
22 @Test(groups = "Functional")
23 public void testConstructor()
25 // note score matrix does not have to be symmetric (though it should be!)
26 float[][] scores = new float[3][];
27 scores[0] = new float[] { 1f, 2f, 3f };
28 scores[1] = new float[] { 4f, 5f, 6f };
29 scores[2] = new float[] { 7f, 8f, 9f };
30 ScoreMatrix sm = new ScoreMatrix("Test", "ABC".toCharArray(), scores);
31 assertEquals(sm.getSize(), 3);
32 assertArrayEquals(scores, sm.getMatrix());
33 assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
34 assertEquals(sm.getPairwiseScore('b', 'c'), 6f);
35 assertEquals(sm.getPairwiseScore('c', 'b'), 8f);
36 assertEquals(sm.getPairwiseScore('A', 'D'), 0f);
37 assertEquals(sm.getMatrixIndex('c'), 2);
38 assertEquals(sm.getMatrixIndex(' '), -1);
42 groups = "Functional",
43 expectedExceptions = { IllegalArgumentException.class })
44 public void testConstructor_matrixTooSmall()
46 float[][] scores = new float[2][];
47 scores[0] = new float[] { 1f, 2f };
48 scores[1] = new float[] { 3f, 4f };
49 new ScoreMatrix("Test", "ABC".toCharArray(), scores);
53 groups = "Functional",
54 expectedExceptions = { IllegalArgumentException.class })
55 public void testConstructor_matrixTooBig()
57 float[][] scores = new float[2][];
58 scores[0] = new float[] { 1f, 2f };
59 scores[1] = new float[] { 3f, 4f };
60 new ScoreMatrix("Test", "A".toCharArray(), scores);
64 groups = "Functional",
65 expectedExceptions = { IllegalArgumentException.class })
66 public void testConstructor_matrixNotSquare()
68 float[][] scores = new float[2][];
69 scores[0] = new float[] { 1f, 2f };
70 scores[1] = new float[] { 3f };
71 new ScoreMatrix("Test", "AB".toCharArray(), scores);
74 @Test(groups = "Functional")
75 public void testBuildSymbolIndex()
77 short[] index = ScoreMatrix.buildSymbolIndex("AX-. yxYp".toCharArray());
79 assertEquals(index.length, 128); // ASCII character set size
81 assertEquals(index['A'], 0);
82 assertEquals(index['a'], 0); // lower-case mapping added
83 assertEquals(index['X'], 1);
84 assertEquals(index['-'], 2);
85 assertEquals(index['.'], 3);
86 assertEquals(index[' '], 4);
87 assertEquals(index['y'], 5); // lower-case override
88 assertEquals(index['x'], 6); // lower-case override
89 assertEquals(index['Y'], 7);
90 assertEquals(index['p'], 8);
91 assertEquals(index['P'], -1); // lower-case doesn't map upper-case
94 * check all unmapped symbols have index for unmapped
96 for (int c = 0; c < index.length; c++)
98 if (!"AaXx-. Yyp".contains(String.valueOf((char) c)))
100 assertEquals(index[c], -1);
106 * check that characters not in the basic ASCII set are simply ignored
108 @Test(groups = "Functional")
109 public void testBuildSymbolIndex_nonAscii()
111 char[] weird = new char[] { 128, 245, 'P' };
112 short[] index = ScoreMatrix.buildSymbolIndex(weird);
113 assertEquals(index.length, 128);
114 assertEquals(index['P'], 2);
115 assertEquals(index['p'], 2);
116 for (int c = 0; c < index.length; c++)
118 if (c != 'P' && c != 'p')
120 assertEquals(index[c], -1);
125 @Test(groups = "Functional")
126 public void testGetMatrix()
128 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
129 float[][] m = sm.getMatrix();
130 assertEquals(m.length, sm.getSize());
131 assertEquals(m[2][4], -3f);
132 // verify a defensive copy is returned
133 float[][] m2 = sm.getMatrix();
134 assertNotSame(m, m2);
135 assertTrue(Arrays.deepEquals(m, m2));
138 @Test(groups = "Functional")
139 public void testGetMatrixIndex()
141 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
142 assertEquals(sm.getMatrixIndex('A'), 0);
143 assertEquals(sm.getMatrixIndex('R'), 1);
144 assertEquals(sm.getMatrixIndex('r'), 1);
145 assertEquals(sm.getMatrixIndex('N'), 2);
146 assertEquals(sm.getMatrixIndex('D'), 3);
147 assertEquals(sm.getMatrixIndex('X'), 22);
148 assertEquals(sm.getMatrixIndex('x'), 22);
149 assertEquals(sm.getMatrixIndex(' '), 23);
150 assertEquals(sm.getMatrixIndex('*'), 24);
151 assertEquals(sm.getMatrixIndex('.'), -1);
152 assertEquals(sm.getMatrixIndex('-'), -1);
153 assertEquals(sm.getMatrixIndex('?'), -1);
154 assertEquals(sm.getMatrixIndex((char) 128), -1);
157 @Test(groups = "Functional")
158 public void testGetSize()
160 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
161 assertEquals(sm.getMatrix().length, sm.getSize());
164 @Test(groups = "Functional")
165 public void testComputePairwiseScores()
168 * NB score matrix assumes space for gap - Jalview converts
169 * space to gap before computing PCA or Tree
171 String[] seqs = new String[] { "FKL", "R D", "QIA", "GWC" };
172 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
174 MatrixI pairwise = sm.findSimilarities(seqs, SimilarityParams.Jalview);
177 * should be NxN where N = number of sequences
179 assertEquals(pairwise.height(), 4);
180 assertEquals(pairwise.width(), 4);
183 * should be symmetrical (because BLOSUM62 is)
185 for (int i = 0; i < pairwise.height(); i++)
187 for (int j = i + 1; j < pairwise.width(); j++)
189 assertEquals(pairwise.getValue(i, j), pairwise.getValue(j, i),
190 String.format("Not symmetric at [%d, %d]", i, j));
194 * verify expected BLOSUM dot product scores
196 // F.F + K.K + L.L = 6 + 5 + 4 = 15
197 assertEquals(pairwise.getValue(0, 0), 15d);
198 // R.R + -.- + D.D = 5 + 1 + 6 = 12
199 assertEquals(pairwise.getValue(1, 1), 12d);
200 // Q.Q + I.I + A.A = 5 + 4 + 4 = 13
201 assertEquals(pairwise.getValue(2, 2), 13d);
202 // G.G + W.W + C.C = 6 + 11 + 9 = 26
203 assertEquals(pairwise.getValue(3, 3), 26d);
204 // F.R + K.- + L.D = -3 + -4 + -4 = -11
205 assertEquals(pairwise.getValue(0, 1), -11d);
206 // F.Q + K.I + L.A = -3 + -3 + -1 = -7
207 assertEquals(pairwise.getValue(0, 2), -7d);
208 // F.G + K.W + L.C = -3 + -3 + -1 = -7
209 assertEquals(pairwise.getValue(0, 3), -7d);
210 // R.Q + -.I + D.A = 1 + -4 + -2 = -5
211 assertEquals(pairwise.getValue(1, 2), -5d);
212 // R.G + -.W + D.C = -2 + -4 + -3 = -9
213 assertEquals(pairwise.getValue(1, 3), -9d);
214 // Q.G + I.W + A.C = -2 + -3 + 0 = -5
215 assertEquals(pairwise.getValue(2, 3), -5d);
219 * Test that the result of outputMatrix can be reparsed to give an identical
222 * @throws IOException
223 * @throws MalformedURLException
225 @Test(groups = "Functional")
226 public void testOutputMatrix_roundTrip() throws MalformedURLException,
229 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
230 String output = sm.outputMatrix(false);
231 FileParse fp = new FileParse(output, DataSourceType.PASTE);
232 ScoreMatrixFile parser = new ScoreMatrixFile(fp);
233 ScoreMatrix sm2 = parser.parseMatrix();
235 assertTrue(sm2.equals(sm));
238 @Test(groups = "Functional")
239 public void testEqualsAndHashCode()
241 ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
242 ScoreMatrix sm2 = new ScoreMatrix(sm.getName(), sm.getSymbols()
243 .toCharArray(), sm.getMatrix());
244 assertTrue(sm.equals(sm2));
245 assertEquals(sm.hashCode(), sm2.hashCode());