JAL-1270 JAL-2416 JAL-2839 set alwaysRun=true in test AfterMethod!
[jalview.git] / test / jalview / io / ScoreMatrixFileTest.java
1 package jalview.io;
2
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertFalse;
5 import static org.testng.Assert.assertNotNull;
6 import static org.testng.Assert.assertNull;
7 import static org.testng.Assert.assertTrue;
8 import static org.testng.Assert.fail;
9
10 import jalview.analysis.scoremodels.ScoreMatrix;
11 import jalview.analysis.scoremodels.ScoreModels;
12
13 import java.io.IOException;
14 import java.net.MalformedURLException;
15
16 import org.testng.annotations.AfterMethod;
17 import org.testng.annotations.Test;
18
19 public class ScoreMatrixFileTest
20 {
21
22   @AfterMethod(alwaysRun=true)
23   public void tearDownAfterTest()
24   {
25     ScoreModels.getInstance().reset();
26   }
27
28   /**
29    * Test a successful parse of a (small) score matrix file
30    * 
31    * @throws IOException
32    * @throws MalformedURLException
33    */
34   @Test(groups = "Functional")
35   public void testParseMatrix_ncbiMixedDelimiters()
36           throws MalformedURLException,
37           IOException
38   {
39     /*
40      * some messy but valid input data, with comma, space
41      * or tab (or combinations) as score value delimiters
42      * this example includes 'guide' symbols on score rows
43      */
44     String data = "ScoreMatrix MyTest (example)\n" + "A\tT\tU\tt\tx\t-\n"
45             + "A,1.1,1.2,1.3,1.4, 1.5, 1.6\n"
46             + "T,2.1 2.2 2.3 2.4 2.5 2.6\n"
47             + "U\t3.1\t3.2\t3.3\t3.4\t3.5\t3.6\t\n"
48             + "t, 5.1,5.3,5.3,5.4,5.5, 5.6\n"
49             + "x\t6.1, 6.2 6.3 6.4 6.5 6.6\n"
50             + "-, \t7.1\t7.2 7.3, 7.4, 7.5\t,7.6\n";
51     FileParse fp = new FileParse(data, DataSourceType.PASTE);
52     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
53     ScoreMatrix sm = parser.parseMatrix();
54
55     assertNotNull(sm);
56     assertEquals(sm.getName(), "MyTest (example)");
57     assertEquals(sm.getSize(), 6);
58     assertNull(sm.getDescription());
59     assertTrue(sm.isDNA());
60     assertFalse(sm.isProtein());
61     assertEquals(sm.getMinimumScore(), 1.1f);
62     assertEquals(sm.getPairwiseScore('A', 'A'), 1.1f);
63     assertEquals(sm.getPairwiseScore('A', 'T'), 1.2f);
64     assertEquals(sm.getPairwiseScore('a', 'T'), 1.2f); // A/a equivalent
65     assertEquals(sm.getPairwiseScore('A', 't'), 1.4f); // T/t not equivalent
66     assertEquals(sm.getPairwiseScore('a', 't'), 1.4f);
67     assertEquals(sm.getPairwiseScore('U', 'x'), 3.5f);
68     assertEquals(sm.getPairwiseScore('u', 'x'), 3.5f);
69     // X (upper) and '.' unmapped - get minimum score
70     assertEquals(sm.getPairwiseScore('U', 'X'), 1.1f);
71     assertEquals(sm.getPairwiseScore('A', '.'), 1.1f);
72     assertEquals(sm.getPairwiseScore('-', '-'), 7.6f);
73     assertEquals(sm.getPairwiseScore('A', (char) 128), 0f); // out of range
74   }
75
76   @Test(groups = "Functional")
77   public void testParseMatrix_headerMissing()
78   {
79     String data;
80
81     data = "X Y\n1 2\n3 4\n";
82     try
83     {
84       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
85               .parseMatrix();
86       fail("expected exception");
87     } catch (IOException e)
88     {
89       assertEquals(e.getMessage(),
90               "Format error: 'ScoreMatrix <name>' should be the first non-comment line");
91     }
92   }
93
94   @Test(groups = "Functional")
95   public void testParseMatrix_ncbiNotEnoughRows()
96   {
97     String data = "ScoreMatrix MyTest\nX Y Z\n1 2 3\n4 5 6\n";
98     try
99     {
100       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
101               .parseMatrix();
102       fail("expected exception");
103     } catch (IOException e)
104     {
105       assertEquals(e.getMessage(),
106               "Expected 3 rows of score data in score matrix but only found 2");
107     }
108   }
109
110   @Test(groups = "Functional")
111   public void testParseMatrix_ncbiNotEnoughColumns()
112   {
113     String data = "ScoreMatrix MyTest\nX Y Z\n1 2 3\n4 5\n7 8 9\n";
114     try
115     {
116       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
117               .parseMatrix();
118       fail("expected exception");
119     } catch (IOException e)
120     {
121       assertEquals(e.getMessage(),
122               "Expected 3 scores at line 4: '4 5' but found 2");
123     }
124   }
125
126   @Test(groups = "Functional")
127   public void testParseMatrix_ncbiTooManyColumns()
128   {
129     /*
130      * with two too many columns:
131      */
132     String data = "ScoreMatrix MyTest\nX\tY\tZ\n1 2 3\n4 5 6 7\n8 9 10\n";
133     try
134     {
135       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
136               .parseMatrix();
137       fail("expected exception");
138     } catch (IOException e)
139     {
140       assertEquals(e.getMessage(),
141               "Expected 3 scores at line 4: '4 5 6 7' but found 4");
142     }
143
144     /*
145      * with guide character and one too many columns:
146      */
147     data = "ScoreMatrix MyTest\nX Y\nX 1 2\nY 3 4 5\n";
148     try
149     {
150       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
151               .parseMatrix();
152       fail("expected exception");
153     } catch (IOException e)
154     {
155       assertEquals(e.getMessage(),
156               "Expected 2 scores at line 4: 'Y 3 4 5' but found 3");
157     }
158
159     /*
160      * with no guide character and one too many columns
161      */
162     data = "ScoreMatrix MyTest\nX Y\n1 2\n3 4 5\n";
163     try
164     {
165       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
166               .parseMatrix();
167       fail("expected exception");
168     } catch (IOException e)
169     {
170       assertEquals(e.getMessage(),
171               "Expected 2 scores at line 4: '3 4 5' but found 3");
172     }
173   }
174
175   @Test(groups = "Functional")
176   public void testParseMatrix_ncbiTooManyRows()
177   {
178     String data = "ScoreMatrix MyTest\n\tX\tY\tZ\n1 2 3\n4 5 6\n7 8 9\n10 11 12\n";
179     try
180     {
181       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
182               .parseMatrix();
183       fail("expected exception");
184     } catch (IOException e)
185     {
186       assertEquals(e.getMessage(),
187               "Unexpected extra input line in score model file: '10 11 12'");
188     }
189   }
190
191   @Test(groups = "Functional")
192   public void testParseMatrix_ncbiBadDelimiter()
193   {
194     String data = "ScoreMatrix MyTest\n X Y Z\n1|2|3\n4|5|6\n";
195     try
196     {
197       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
198               .parseMatrix();
199       fail("expected exception");
200     } catch (IOException e)
201     {
202       assertEquals(e.getMessage(),
203               "Invalid score value '1|2|3' at line 3 column 0");
204     }
205   }
206
207   @Test(groups = "Functional")
208   public void testParseMatrix_ncbiBadFloat()
209   {
210     String data = "ScoreMatrix MyTest\n\tX\tY\tZ\n1 2 3\n4 five 6\n7 8 9\n";
211     try
212     {
213       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
214               .parseMatrix();
215       fail("expected exception");
216     } catch (IOException e)
217     {
218       assertEquals(e.getMessage(),
219               "Invalid score value 'five' at line 4 column 1");
220     }
221   }
222
223   @Test(groups = "Functional")
224   public void testParseMatrix_ncbiBadGuideCharacter()
225   {
226     String data = "ScoreMatrix MyTest\n\tX Y\nX 1 2\ny 3 4\n";
227     try
228     {
229       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
230               .parseMatrix();
231       fail("expected exception");
232     } catch (IOException e)
233     {
234       assertEquals(e.getMessage(),
235               "Error parsing score matrix at line 4, expected 'Y' but found 'y'");
236     }
237
238     data = "ScoreMatrix MyTest\n\tX Y\nXX 1 2\nY 3 4\n";
239     try
240     {
241       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
242               .parseMatrix();
243       fail("expected exception");
244     } catch (IOException e)
245     {
246       assertEquals(e.getMessage(),
247               "Error parsing score matrix at line 3, expected 'X' but found 'XX'");
248     }
249   }
250
251   @Test(groups = "Functional")
252   public void testParseMatrix_ncbiNameMissing()
253   {
254     /*
255      * Name missing on ScoreMatrix header line
256      */
257     String data = "ScoreMatrix\nX Y\n1 2\n3 4\n";
258     try
259     {
260       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
261               .parseMatrix();
262       fail("expected exception");
263     } catch (IOException e)
264     {
265       assertEquals(
266               e.getMessage(),
267               "Format error: expected 'ScoreMatrix <name>', found 'ScoreMatrix' at line 1");
268     }
269   }
270
271   /**
272    * Test a successful parse of a (small) score matrix file
273    * 
274    * @throws IOException
275    * @throws MalformedURLException
276    */
277   @Test(groups = "Functional")
278   public void testParseMatrix_ncbiFormat() throws MalformedURLException,
279           IOException
280   {
281     // input including comment and blank lines
282     String data = "ScoreMatrix MyTest\n#comment\n\n" + "\tA\tB\tC\n"
283             + "A\t1.0\t2.0\t3.0\n" + "B\t4.0\t5.0\t6.0\n"
284             + "C\t7.0\t8.0\t9.0\n";
285     FileParse fp = new FileParse(data, DataSourceType.PASTE);
286     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
287     ScoreMatrix sm = parser.parseMatrix();
288   
289     assertNotNull(sm);
290     assertEquals(sm.getName(), "MyTest");
291     assertEquals(parser.getMatrixName(), "MyTest");
292     assertEquals(sm.getPairwiseScore('A', 'A'), 1.0f);
293     assertEquals(sm.getPairwiseScore('B', 'c'), 6.0f);
294     assertEquals(sm.getSize(), 3);
295   }
296
297   /**
298    * Test a successful parse of a (small) score matrix file
299    * 
300    * @throws IOException
301    * @throws MalformedURLException
302    */
303   @Test(groups = "Functional")
304   public void testParseMatrix_aaIndexBlosum80()
305           throws MalformedURLException,
306           IOException
307   {
308     FileParse fp = new FileParse("resources/scoreModel/blosum80.scm",
309             DataSourceType.FILE);
310     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
311     ScoreMatrix sm = parser.parseMatrix();
312   
313     assertNotNull(sm);
314     assertEquals(sm.getName(), "HENS920103");
315     assertEquals(sm.getDescription(),
316             "BLOSUM80 substitution matrix (Henikoff-Henikoff, 1992)");
317     assertFalse(sm.isDNA());
318     assertTrue(sm.isProtein());
319     assertEquals(20, sm.getSize());
320
321     assertEquals(sm.getPairwiseScore('A', 'A'), 7f);
322     assertEquals(sm.getPairwiseScore('A', 'R'), -3f);
323     assertEquals(sm.getPairwiseScore('r', 'a'), -3f); // A/a equivalent
324   }
325
326   /**
327    * Test a successful parse of a (small) score matrix file
328    * 
329    * @throws IOException
330    * @throws MalformedURLException
331    */
332   @Test(groups = "Functional")
333   public void testParseMatrix_aaindexFormat() throws MalformedURLException,
334           IOException
335   {
336     /*
337      * aaindex format has scores for diagonal and below only
338      */
339     String data = "H MyTest\n" + "D My description\n" + "R PMID:1438297\n"
340             + "A Authors, names\n" + "T Journal title\n"
341             + "J Journal reference\n" + "* matrix in 1/3 Bit Units\n"
342             + "M rows = ABC, cols = ABC\n" + "A\t1.0\n"
343             + "B\t4.0\t5.0\n"
344             + "C\t7.0\t8.0\t9.0\n";
345     FileParse fp = new FileParse(data, DataSourceType.PASTE);
346     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
347     ScoreMatrix sm = parser.parseMatrix();
348   
349     assertNotNull(sm);
350     assertEquals(sm.getSize(), 3);
351     assertEquals(sm.getName(), "MyTest");
352     assertEquals(sm.getDescription(), "My description");
353     assertEquals(sm.getPairwiseScore('A', 'A'), 1.0f);
354     assertEquals(sm.getPairwiseScore('A', 'B'), 4.0f);
355     assertEquals(sm.getPairwiseScore('A', 'C'), 7.0f);
356     assertEquals(sm.getPairwiseScore('B', 'A'), 4.0f);
357     assertEquals(sm.getPairwiseScore('B', 'B'), 5.0f);
358     assertEquals(sm.getPairwiseScore('B', 'C'), 8.0f);
359     assertEquals(sm.getPairwiseScore('C', 'C'), 9.0f);
360     assertEquals(sm.getPairwiseScore('C', 'B'), 8.0f);
361     assertEquals(sm.getPairwiseScore('C', 'A'), 7.0f);
362   }
363
364   @Test(groups = "Functional")
365   public void testParseMatrix_aaindex_mMissing()
366           throws MalformedURLException,
367           IOException
368   {
369     /*
370      * aaindex format but M cols=, rows= is missing
371      */
372     String data = "H MyTest\n" + "A\t1.0\n"
373             + "B\t4.0\t5.0\n"
374             + "C\t7.0\t8.0\t9.0\n";
375     FileParse fp = new FileParse(data, DataSourceType.PASTE);
376     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
377     try
378     {
379       parser.parseMatrix();
380       fail("Expected exception");
381     } catch (FileFormatException e)
382     {
383       assertEquals(e.getMessage(), "No alphabet specified in matrix file");
384     }
385   }
386
387   @Test(groups = "Functional")
388   public void testParseMatrix_aaindex_rowColMismatch()
389           throws MalformedURLException,
390           IOException
391   {
392     String data = "H MyTest\n" + "M rows=ABC, cols=ABD\n" + "A\t1.0\n"
393             + "B\t4.0\t5.0\n"
394             + "C\t7.0\t8.0\t9.0\n";
395     FileParse fp = new FileParse(data, DataSourceType.PASTE);
396     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
397     try
398     {
399       parser.parseMatrix();
400       fail("Expected exception");
401     } catch (FileFormatException e)
402     {
403       assertEquals(
404               e.getMessage(),
405               "Unexpected aaIndex score matrix data at line 2: M rows=ABC, cols=ABD rows != cols");
406     }
407   }
408
409   @Test(groups = "Functional")
410   public void testParseMatrix_ncbiHeaderRepeated()
411   {
412     String data = "ScoreMatrix BLOSUM\nScoreMatrix PAM250\nX Y\n1 2\n3 4\n";
413     try
414     {
415       new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
416               .parseMatrix();
417       fail("expected exception");
418     } catch (IOException e)
419     {
420       assertEquals(e.getMessage(),
421               "Error: 'ScoreMatrix' repeated in file at line 2");
422     }
423   }
424
425   @Test(groups = "Functional")
426   public void testParseMatrix_aaindex_tooManyRows()
427           throws MalformedURLException,
428           IOException
429   {
430     String data = "H MyTest\n" + "M rows=ABC, cols=ABC\n" + "A\t1.0\n"
431             + "B\t4.0\t5.0\n" + "C\t7.0\t8.0\t9.0\n" + "C\t7.0\t8.0\t9.0\n";
432     FileParse fp = new FileParse(data, DataSourceType.PASTE);
433     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
434     try
435     {
436       parser.parseMatrix();
437       fail("Expected exception");
438     } catch (FileFormatException e)
439     {
440       assertEquals(e.getMessage(), "Too many data rows in matrix file");
441     }
442   }
443
444   @Test(groups = "Functional")
445   public void testParseMatrix_aaindex_extraDataLines()
446           throws MalformedURLException,
447           IOException
448   {
449     String data = "H MyTest\n" + "M rows=ABC, cols=ABC\n" + "A\t1.0\n"
450             + "B\t4.0\t5.0\n" + "C\t7.0\t8.0\t9.0\n" + "something extra\n";
451     FileParse fp = new FileParse(data, DataSourceType.PASTE);
452     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
453     try
454     {
455       parser.parseMatrix();
456       fail("Expected exception");
457     } catch (FileFormatException e)
458     {
459       assertEquals(e.getMessage(), "Too many data rows in matrix file");
460     }
461   }
462
463   @Test(groups = "Functional")
464   public void testParseMatrix_aaindex_tooFewColumns()
465           throws MalformedURLException,
466           IOException
467   {
468     String data = "H MyTest\n" + "M rows=ABC, cols=ABC\n" + "A\t1.0\n"
469             + "B\t4.0\t5.0\n" + "C\t7.0\t8.0\n";
470     FileParse fp = new FileParse(data, DataSourceType.PASTE);
471     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
472     try
473     {
474       parser.parseMatrix();
475       fail("Expected exception");
476     } catch (FileFormatException e)
477     {
478       assertEquals(
479               e.getMessage(),
480               "Expected 3 scores at line 5: 'C\t7.0\t8.0' but found 2");
481     }
482   }
483
484   /**
485    * Test a successful parse and register of a score matrix file
486    * 
487    * @throws IOException
488    * @throws MalformedURLException
489    */
490   @Test(groups = "Functional")
491   public void testParse_ncbiFormat() throws MalformedURLException,
492           IOException
493   {
494     assertNull(ScoreModels.getInstance().getScoreModel("MyNewTest", null));
495
496     String data = "ScoreMatrix MyNewTest\n" + "\tA\tB\tC\n"
497             + "A\t1.0\t2.0\t3.0\n" + "B\t4.0\t5.0\t6.0\n"
498             + "C\t7.0\t8.0\t9.0\n";
499     FileParse fp = new FileParse(data, DataSourceType.PASTE);
500     ScoreMatrixFile parser = new ScoreMatrixFile(fp);
501
502     parser.parse();
503   
504     ScoreMatrix sm = (ScoreMatrix) ScoreModels.getInstance().getScoreModel(
505             "MyNewTest", null);
506     assertNotNull(sm);
507     assertEquals(sm.getName(), "MyNewTest");
508     assertEquals(parser.getMatrixName(), "MyNewTest");
509     assertEquals(sm.getPairwiseScore('A', 'A'), 1.0f);
510     assertEquals(sm.getPairwiseScore('B', 'c'), 6.0f);
511     assertEquals(sm.getSize(), 3);
512   }
513 }