JAL-4386_Added changes in similarity score calculation for different cases of sequenc...
[jalview.git] / test / jalview / analysis / scoremodels / SecondaryStructureDistanceModelTest.java
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.assertTrue;
25
26 import jalview.api.analysis.ScoreModelI;
27 import jalview.api.analysis.SimilarityParamsI;
28 import jalview.datamodel.Alignment;
29 import jalview.datamodel.AlignmentAnnotation;
30 import jalview.datamodel.AlignmentI;
31 import jalview.datamodel.AlignmentView;
32 import jalview.datamodel.Annotation;
33 import jalview.datamodel.Sequence;
34 import jalview.datamodel.SequenceFeature;
35 import jalview.datamodel.SequenceI;
36 import jalview.gui.AlignFrame;
37 import jalview.gui.AlignViewport;
38 import jalview.gui.JvOptionPane;
39 import jalview.io.DataSourceType;
40 import jalview.io.FileLoader;
41 import jalview.math.MatrixI;
42
43 import org.testng.Assert;
44 import org.testng.annotations.BeforeClass;
45 import org.testng.annotations.Test;
46
47 // This class tests methods in Class SecondaryStructureDistanceModel 
48 public class SecondaryStructureDistanceModelTest
49 {
50
51   @BeforeClass(alwaysRun = true)
52   public void setUpJvOptionPane()
53   {
54     JvOptionPane.setInteractiveMode(false);
55     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
56   }
57
58   public static String alntestFile = "FER1_MESCR/72-76 DVYIL\nFER1_SPIOL/71-75 DVYIL\nFER3_RAPSA/21-25 DVYVL\nFER1_MAIZE/73-77 DVYIL\n";
59
60   int[] sf1 = new int[] { 74, 74, 73, 73, 23, 23, -1, -1 };
61
62   int[] sf2 = new int[] { -1, -1, 74, 75, -1, -1, 76, 77 };
63
64   int[] sf3 = new int[] { -1, -1, -1, -1, -1, -1, 76, 77 };
65
66   /**
67    * <pre>
68    * Load test alignment and add features to sequences: 
69    *      FER1_MESCR FER1_SPIOL FER3_RAPSA FER1_MAIZE 
70    *  sf1     X          X          X  
71    *  sf2                X                     X 
72    *  sf3                                      X
73    * </pre>
74    * 
75    * @return
76    */
77   public AlignFrame getTestAlignmentFrame()
78   {
79     AlignFrame alf = new FileLoader(false)
80             .LoadFileWaitTillLoaded(alntestFile, DataSourceType.PASTE);
81     AlignmentI al = alf.getViewport().getAlignment();
82     Assert.assertEquals(al.getHeight(), 4);
83     Assert.assertEquals(al.getWidth(), 5);
84     for (int i = 0; i < 4; i++)
85     {
86       SequenceI ds = al.getSequenceAt(i).getDatasetSequence();
87       if (sf1[i * 2] > 0)
88       {
89         ds.addSequenceFeature(new SequenceFeature("sf1", "sf1", sf1[i * 2],
90                 sf1[i * 2 + 1], "sf1"));
91       }
92       if (sf2[i * 2] > 0)
93       {
94         ds.addSequenceFeature(new SequenceFeature("sf2", "sf2", sf2[i * 2],
95                 sf2[i * 2 + 1], "sf2"));
96       }
97       if (sf3[i * 2] > 0)
98       {
99         ds.addSequenceFeature(new SequenceFeature("sf3", "sf3", sf3[i * 2],
100                 sf3[i * 2 + 1], "sf3"));
101       }
102     }
103     alf.setShowSeqFeatures(true);
104     alf.getFeatureRenderer().setVisible("sf1");
105     alf.getFeatureRenderer().setVisible("sf2");
106     alf.getFeatureRenderer().setVisible("sf3");
107     alf.getFeatureRenderer().findAllFeatures(true);
108     Assert.assertEquals(
109             alf.getFeatureRenderer().getDisplayedFeatureTypes().size(), 3,
110             "Number of feature types");
111     assertTrue(alf.getCurrentView().areFeaturesDisplayed());
112     return alf;
113   }
114
115
116
117   /**
118    * Verify computed distances of sequences with similar secondary structures
119    */
120   @Test(groups = "Functional")
121   public void testFindDistances_AllSimilar()
122   {
123     AlignFrame af = setupAlignmentView("All Similar");
124     AlignViewport viewport = af.getViewport();
125     AlignmentView view = viewport.getAlignmentView(false);
126
127     ScoreModelI sm = new SecondaryStructureDistanceModel();
128     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
129             af.alignPanel);
130
131     /*
132      * feature distance model always normalises by region width
133      */
134
135     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
136     MatrixI distances = sm.findDistances(view, params);
137     assertEquals(distances.getValue(0, 0), 0d);
138     assertEquals(distances.getValue(1, 1), 0d);
139     assertEquals(distances.getValue(0, 1), 0d / 4); 
140     assertEquals(distances.getValue(1, 0), 0d / 4);
141   }
142   
143   /**
144    * Verify computed distances of sequences with partially similar secondary structures
145    */
146   @Test(groups = "Functional")
147   public void testFindDistances_PartiallySimilar()
148   {
149     AlignFrame af = setupAlignmentView("Partially Similar");
150     AlignViewport viewport = af.getViewport();
151     AlignmentView view = viewport.getAlignmentView(false);
152
153     ScoreModelI sm = new SecondaryStructureDistanceModel();
154     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
155             af.alignPanel);
156
157     /*
158      * score = 0 + 0 + 2 + 2 = 4/4
159      */
160     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
161     MatrixI distances = sm.findDistances(view, params);
162     assertEquals(distances.getValue(0, 0), 0d);
163     assertEquals(distances.getValue(1, 1), 0d);
164     assertEquals(distances.getValue(0, 1), 1d); // should be 13d/6
165     assertEquals(distances.getValue(1, 0), 1d);
166   }
167   
168   /**
169    * Verify computed distances of sequences with dissimilar secondary structures
170    */
171   @Test(groups = "Functional")
172   public void testFindDistances_notSimilar()
173   {
174     AlignFrame af = setupAlignmentView("Not Similar");
175     AlignViewport viewport = af.getViewport();
176     AlignmentView view = viewport.getAlignmentView(false);
177
178     ScoreModelI sm = new SecondaryStructureDistanceModel();
179     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
180             af.alignPanel);
181
182     /*
183      * score = 2 + 2 + 2 + 2 = 8/4
184      */
185     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
186     MatrixI distances = sm.findDistances(view, params);
187     assertEquals(distances.getValue(0, 0), 0d);
188     assertEquals(distances.getValue(1, 1), 0d);
189     assertEquals(distances.getValue(0, 1), 2d); 
190     assertEquals(distances.getValue(1, 0), 2d);
191   }
192   
193   /**
194    * Verify computed distances of sequences with dissimilar secondary structures
195    * with coil structure represented as null
196    */
197   @Test(groups = "Functional")
198   public void testFindDistances_withCoil()
199   {
200     AlignFrame af = setupAlignmentView("With Coil");
201     AlignViewport viewport = af.getViewport();
202     AlignmentView view = viewport.getAlignmentView(false);
203
204     ScoreModelI sm = new SecondaryStructureDistanceModel();
205     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
206             af.alignPanel);
207
208     /*
209      * score = 2 + 2 + 2 + 2 = 8/4
210      */
211     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
212     MatrixI distances = sm.findDistances(view, params);
213     assertEquals(distances.getValue(0, 0), 0d);
214     assertEquals(distances.getValue(1, 1), 0d);
215     assertEquals(distances.getValue(0, 1), 2d); 
216     assertEquals(distances.getValue(1, 0), 2d);
217   }
218   
219   /**
220    * Verify computed distances of sequences with gap
221    */
222   @Test(groups = "Functional")
223   public void testFindDistances_withGap()
224   {
225     AlignFrame af = setupAlignmentViewWithGap();
226     AlignViewport viewport = af.getViewport();
227     AlignmentView view = viewport.getAlignmentView(false);
228
229     ScoreModelI sm = new SecondaryStructureDistanceModel();
230     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
231             af.alignPanel);
232     
233     /*
234      * feature distance model always normalises by region width
235      * gap-gap is always included (but scores zero)
236      * the only variable parameter is 'includeGaps'
237      */
238
239     /*
240      * include gaps
241      * score = 0 + 0 + 1 + 0 = 1/4
242      */
243     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
244     MatrixI distances = sm.findDistances(view, params);
245     assertEquals(distances.getValue(0, 0), 0d);
246     assertEquals(distances.getValue(1, 1), 0d);
247     assertEquals(distances.getValue(0, 1), 1d/4); 
248     assertEquals(distances.getValue(1, 0), 1d/4);
249     
250     /*
251      * exclude gaps
252      * score = 0 + 0 + 0 + 0 = 0/4
253      */
254     
255     SimilarityParamsI params2 = new SimilarityParams(false, true, false, true);
256     MatrixI distances2 = sm.findDistances(view, params2);
257     assertEquals(distances2.getValue(0, 1), 0d); 
258     assertEquals(distances2.getValue(1, 0), 0d);
259   }
260   
261   
262   /**
263    * Verify computed distances of sequences with gap
264    */
265   @Test(groups = "Functional")
266   public void testFindDistances_withSSUndefinedInEitherOneSeq()
267   {
268     AlignFrame af = setupAlignmentViewWithoutSS("either");
269     AlignViewport viewport = af.getViewport();
270     AlignmentView view = viewport.getAlignmentView(false);
271
272     ScoreModelI sm = new SecondaryStructureDistanceModel();
273     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
274             af.alignPanel);
275     
276     /*
277      * feature distance model always normalises by region width
278      * gap-gap is always included (but scores zero)
279      * the only variable parameter is 'includeGaps'
280      */
281
282     /*
283      * include gaps
284      * score = 0 + 0 + 2 + 2 = 2/4
285      */
286     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
287     MatrixI distances = sm.findDistances(view, params);
288     assertEquals(distances.getValue(0, 0), 0d);
289     assertEquals(distances.getValue(1, 1), 0d);
290     assertEquals(distances.getValue(0, 1), 2d); 
291     assertEquals(distances.getValue(1, 0), 2d);
292     
293     /*
294      * exclude gaps
295      * score = 0 + 0 + 2 + 2 = 2/4
296      */
297     
298     SimilarityParamsI params2 = new SimilarityParams(false, true, false, true);
299     MatrixI distances2 = sm.findDistances(view, params2);
300     assertEquals(distances2.getValue(0, 1), 2d); 
301     assertEquals(distances2.getValue(1, 0), 2d);
302   }
303
304   
305   /**
306    * Verify computed distances of sequences with gap
307    */
308   @Test(groups = "Functional")
309   public void testFindDistances_withSSUndefinedInBothSeqs()
310   {
311     AlignFrame af = setupAlignmentViewWithoutSS("both");
312     AlignViewport viewport = af.getViewport();
313     AlignmentView view = viewport.getAlignmentView(false);
314
315     ScoreModelI sm = new SecondaryStructureDistanceModel();
316     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
317             af.alignPanel);
318     
319     /*
320      * feature distance model always normalises by region width
321      * gap-gap is always included (but scores zero)
322      * the only variable parameter is 'includeGaps'
323      */
324
325     /*
326      * include gaps
327      * score = 0 + 0 + 2 + 2 = 2/4
328      */
329     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
330     MatrixI distances = sm.findDistances(view, params);
331     assertEquals(distances.getValue(0, 0), 0d);
332     assertEquals(distances.getValue(1, 1), 0d);
333     assertEquals(distances.getValue(0, 1), 0d); 
334     assertEquals(distances.getValue(1, 0), 0d);
335     
336     /*
337      * exclude gaps
338      * score = 0 + 0 + 2 + 2 = 2/4
339      */
340     
341     SimilarityParamsI params2 = new SimilarityParams(false, true, false, true);
342     MatrixI distances2 = sm.findDistances(view, params2);
343     assertEquals(distances2.getValue(0, 1), 0d); 
344     assertEquals(distances2.getValue(1, 0), 0d);
345   }
346
347
348   
349   /**
350    * <pre>
351    * Set up
352    *   column      1 2 3 4 
353    *        seq s1 F R K S
354    *        
355    *        seq s2 F S J L
356    * </pre>
357    * 
358    * @return
359    */
360   protected AlignFrame setupAlignmentView(String similar)
361   {
362     /*
363      * sequences without gaps
364      */
365     SequenceI s1 = new Sequence("s1", "FRKS");
366     SequenceI s2 = new Sequence("s2", "FSJL");
367
368     s1.addSequenceFeature(
369             new SequenceFeature("chain", null, 1, 4, 0f, null));
370     s1.addSequenceFeature(
371             new SequenceFeature("domain", null, 1, 4, 0f, null));
372     s2.addSequenceFeature(
373             new SequenceFeature("chain", null, 1, 4, 0f, null));
374     s2.addSequenceFeature(
375             new SequenceFeature("metal", null, 1, 4, 0f, null));
376     s2.addSequenceFeature(
377             new SequenceFeature("Pfam", null, 1, 4, 0f, null));
378     
379     
380     /*
381      * Set up secondary structure annotations
382      */
383     Annotation ssE = new Annotation("","",'E',0);
384     Annotation ssH = new Annotation("","",'H',0);
385     Annotation ssC = new Annotation(".","",' ',0);
386     
387     Annotation[] anns1;
388     Annotation[] anns2;
389     
390     /* All secondary structure annotations are similar for each column
391      * Set up
392     *   column      1 2 3 4 
393     *        seq s1 F R K S
394     *            ss E H S E
395     *        
396     *        seq s2 F S J L
397     *            ss E H S E
398     */
399     if(similar == "All Similar") {
400     
401         anns1 = new Annotation[] { ssE, ssH, ssC, ssE};
402         anns2 = new Annotation[] { ssE, ssH, ssC, ssE};
403     
404     }
405     
406     /* All secondary structure annotations are dissimilar for each column
407      * Set up
408      *   column      1 2 3 4 
409      *        seq s1 F R K S
410      *            ss E E C E
411      *        
412      *        seq s2 F S J L
413      *            ss H E E C
414      */
415     else if(similar == "Not Similar") {
416         
417         anns1 = new Annotation[] { ssE, ssE, ssC, ssE};
418         anns2 = new Annotation[] { ssH, ssH, ssE, ssC};
419     
420     }
421     
422     /* All secondary structure annotations are dissimilar for each column
423      * Set up
424      *   column      1 2 3 4 
425      *        seq s1 F R K S
426      *            ss E E C E
427      *        
428      *        seq s2 F S J L
429      *            ss H E E C
430      */
431     else if(similar == "With Coil") {
432         
433       anns1 = new Annotation[] { ssE, ssE, null, ssE};
434       anns2 = new Annotation[] { ssH, ssH, ssE, null};
435     
436     }
437     
438     /*  Set up
439      *   column      1 2 3 4 
440      *        seq s1 F R K S
441      *            ss H E C E
442      *        
443      *        seq s2 F S J L
444      *            ss H E E C
445      */
446     else {
447         
448         anns1 = new Annotation[] { ssH, ssE, ssC, ssE};
449         anns2 = new Annotation[] { ssH, ssE, ssE, ssC};
450     }
451     
452     
453     AlignmentAnnotation ann1 = new AlignmentAnnotation("Secondary Structure",
454             "Secondary Structure", anns1);
455     AlignmentAnnotation ann2 = new AlignmentAnnotation("Secondary Structure",
456             "Secondary Structure", anns2);
457     
458     s1.addAlignmentAnnotation(ann1);
459     s2.addAlignmentAnnotation(ann2);    
460     
461     AlignmentI al = new Alignment(new SequenceI[] { s1, s2 });
462     AlignFrame af = new AlignFrame(al, 300, 300);
463     af.setShowSeqFeatures(true);
464     af.getFeatureRenderer().findAllFeatures(true);
465     return af;
466   }
467   
468
469   /**
470    * <pre>
471    * Set up
472    *   column      1 2 3 4 
473    *        seq s1 F R   S
474    *              SS H E   C
475    *        
476    *        seq s2 F S J L
477    *              ss H E E C
478    * </pre>
479    * 
480    * @return
481    */
482   protected AlignFrame setupAlignmentViewWithGap()
483   {
484     
485     SequenceI s1 = new Sequence("s1", "FR S");
486     SequenceI s2 = new Sequence("s2", "FSJL");
487
488     s1.addSequenceFeature(
489             new SequenceFeature("chain", null, 1, 3, 0f, null));
490     s1.addSequenceFeature(
491             new SequenceFeature("domain", null, 1, 3, 0f, null));
492     s2.addSequenceFeature(
493             new SequenceFeature("chain", null, 1, 4, 0f, null));
494     s2.addSequenceFeature(
495             new SequenceFeature("metal", null, 1, 4, 0f, null));
496     s2.addSequenceFeature(
497             new SequenceFeature("Pfam", null, 1, 4, 0f, null));
498     
499     
500     Annotation ssE = new Annotation("","",'E',0);
501     Annotation ssH = new Annotation("","",'H',0);
502     Annotation ssC = new Annotation(".","",' ',0);
503     
504     Annotation[] anns1;
505     Annotation[] anns2;
506         
507     anns1 = new Annotation[] { ssH, ssE, ssC};
508     anns2 = new Annotation[] { ssH, ssE, ssE, ssC};    
509     
510     AlignmentAnnotation ann1 = new AlignmentAnnotation("Secondary Structure",
511             "Secondary Structure", anns1);
512     AlignmentAnnotation ann2 = new AlignmentAnnotation("Secondary Structure",
513             "Secondary Structure", anns2);
514     
515     s1.addAlignmentAnnotation(ann1);
516     s2.addAlignmentAnnotation(ann2);    
517         
518     AlignmentI al = new Alignment(new SequenceI[] { s1, s2 });
519     AlignFrame af = new AlignFrame(al, 300, 300);
520     af.setShowSeqFeatures(true);
521     af.getFeatureRenderer().findAllFeatures(true);
522     
523     return af;
524   }
525   
526   protected AlignFrame setupAlignmentViewWithoutSS(String type) {
527     
528     SequenceI s1 = new Sequence("s1", "FR S");
529     SequenceI s2 = new Sequence("s2", "FSJL");
530     
531     s1.addSequenceFeature(
532             new SequenceFeature("chain", null, 1, 3, 0f, null));
533     s1.addSequenceFeature(
534             new SequenceFeature("domain", null, 1, 3, 0f, null));
535     s2.addSequenceFeature(
536             new SequenceFeature("chain", null, 1, 4, 0f, null));
537     s2.addSequenceFeature(
538             new SequenceFeature("metal", null, 1, 4, 0f, null));
539     s2.addSequenceFeature(
540             new SequenceFeature("Pfam", null, 1, 4, 0f, null));
541     
542     if(!type.equals("both")) {    
543       Annotation ssE = new Annotation("","",'E',0);
544       Annotation ssH = new Annotation("","",'H',0);
545       Annotation ssC = new Annotation(".","",' ',0);
546       
547       Annotation[] anns1;
548         
549       anns1 = new Annotation[] { ssH, ssE, ssC};
550           
551       AlignmentAnnotation ann1 = new AlignmentAnnotation("Secondary Structure",
552               "Secondary Structure", anns1);    
553   
554       s1.addAlignmentAnnotation(ann1);    
555     }
556     
557     AlignmentI al = new Alignment(new SequenceI[] { s1, s2 });
558     AlignFrame af = new AlignFrame(al, 300, 300);
559     af.setShowSeqFeatures(true);
560     af.getFeatureRenderer().findAllFeatures(true);
561     return af;
562   }
563
564 }