JAL-4386 Calculate tree using secondary structure annotation
[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 gap
195    */
196   @Test(groups = "Functional")
197   public void testFindDistances_withGap()
198   {
199     AlignFrame af = setupAlignmentViewWithGap("Not Similar");
200     AlignViewport viewport = af.getViewport();
201     AlignmentView view = viewport.getAlignmentView(false);
202
203     ScoreModelI sm = new SecondaryStructureDistanceModel();
204     sm = ScoreModels.getInstance().getScoreModel(sm.getName(),
205             af.alignPanel);
206     
207     /*
208      * feature distance model always normalises by region width
209      * gap-gap is always included (but scores zero)
210      * the only variable parameter is 'includeGaps'
211      */
212
213     /*
214      * include gaps
215      * score = 0 + 0 + 1 + 0 = 1/4
216      */
217     SimilarityParamsI params = new SimilarityParams(false, true, true, true);
218     MatrixI distances = sm.findDistances(view, params);
219     assertEquals(distances.getValue(0, 0), 0d);
220     assertEquals(distances.getValue(1, 1), 0d);
221     assertEquals(distances.getValue(0, 1), 1d/4); 
222     assertEquals(distances.getValue(1, 0), 1d/4);
223     
224     /*
225      * exclude gaps
226      * score = 0 + 0 + 0 + 0 = 0/4
227      */
228     
229     SimilarityParamsI params2 = new SimilarityParams(false, true, false, true);
230     MatrixI distances2 = sm.findDistances(view, params2);
231     assertEquals(distances2.getValue(0, 1), 0d); 
232     assertEquals(distances2.getValue(1, 0), 0d);
233   }
234
235
236   
237   /**
238    * <pre>
239    * Set up
240    *   column      1 2 3 4 
241    *        seq s1 F R K S
242    *        
243    *        seq s2 F S J L
244    * </pre>
245    * 
246    * @return
247    */
248   protected AlignFrame setupAlignmentView(String similar)
249   {
250     /*
251      * sequences without gaps
252      */
253     SequenceI s1 = new Sequence("s1", "FRKS");
254     SequenceI s2 = new Sequence("s2", "FSJL");
255
256     s1.addSequenceFeature(
257             new SequenceFeature("chain", null, 1, 4, 0f, null));
258     s1.addSequenceFeature(
259             new SequenceFeature("domain", null, 1, 4, 0f, null));
260     s2.addSequenceFeature(
261             new SequenceFeature("chain", null, 1, 4, 0f, null));
262     s2.addSequenceFeature(
263             new SequenceFeature("metal", null, 1, 4, 0f, null));
264     s2.addSequenceFeature(
265             new SequenceFeature("Pfam", null, 1, 4, 0f, null));
266     
267     
268     /*
269      * Set up secondary structure annotations
270      */
271     Annotation ssE = new Annotation("","",'E',0);
272     Annotation ssH = new Annotation("","",'H',0);
273     Annotation ssS = new Annotation(".","",' ',0);
274     
275     Annotation[] anns1;
276     Annotation[] anns2;
277     
278     /* All secondary structure annotations are similar for each column
279      * Set up
280     *   column      1 2 3 4 
281     *        seq s1 F R K S
282     *            ss E H S E
283     *        
284     *        seq s2 F S J L
285     *            ss E H S E
286     */
287     if(similar == "All Similar") {
288     
289         anns1 = new Annotation[] { ssE, ssH, ssS, ssE};
290         anns2 = new Annotation[] { ssE, ssH, ssS, ssE};
291     
292     }
293     
294     /* All secondary structure annotations are dissimilar for each column
295      * Set up
296      *   column      1 2 3 4 
297      *        seq s1 F R K S
298      *            ss E E S E
299      *        
300      *        seq s2 F S J L
301      *            ss H E E S
302      */
303     else if(similar == "Not Similar") {
304         
305         anns1 = new Annotation[] { ssE, ssE, ssS, ssE};
306         anns2 = new Annotation[] { ssH, ssH, ssE, ssS};
307     
308     }
309     
310     /*  Set up
311      *   column      1 2 3 4 
312      *        seq s1 F R K S
313      *            ss H E S E
314      *        
315      *        seq s2 F S J L
316      *            ss H E E S
317      */
318     else {
319         
320         anns1 = new Annotation[] { ssH, ssE, ssS, ssE};
321         anns2 = new Annotation[] { ssH, ssE, ssE, ssS};
322     }
323     
324     
325     AlignmentAnnotation ann1 = new AlignmentAnnotation("Secondary Structure",
326             "Secondary Structure", anns1);
327     AlignmentAnnotation ann2 = new AlignmentAnnotation("Secondary Structure",
328             "Secondary Structure", anns2);
329     
330     s1.addAlignmentAnnotation(ann1);
331     s2.addAlignmentAnnotation(ann2);    
332     
333     AlignmentI al = new Alignment(new SequenceI[] { s1, s2 });
334     AlignFrame af = new AlignFrame(al, 300, 300);
335     af.setShowSeqFeatures(true);
336     af.getFeatureRenderer().findAllFeatures(true);
337     return af;
338   }
339   
340
341   /**
342    * <pre>
343    * Set up
344    *   column      1 2 3 4 
345    *        seq s1 F R   S
346    *            SS H E   S
347    *        
348    *        seq s2 F S J L
349    *            ss H E E S
350    * </pre>
351    * 
352    * @return
353    */
354   protected AlignFrame setupAlignmentViewWithGap(String similar)
355   {
356     
357     SequenceI s1 = new Sequence("s1", "FR S");
358     SequenceI s2 = new Sequence("s2", "FSJL");
359
360     s1.addSequenceFeature(
361             new SequenceFeature("chain", null, 1, 3, 0f, null));
362     s1.addSequenceFeature(
363             new SequenceFeature("domain", null, 1, 3, 0f, null));
364     s2.addSequenceFeature(
365             new SequenceFeature("chain", null, 1, 4, 0f, null));
366     s2.addSequenceFeature(
367             new SequenceFeature("metal", null, 1, 4, 0f, null));
368     s2.addSequenceFeature(
369             new SequenceFeature("Pfam", null, 1, 4, 0f, null));
370     
371     
372     Annotation ssE = new Annotation("","",'E',0);
373     Annotation ssH = new Annotation("","",'H',0);
374     Annotation ssS = new Annotation(".","",' ',0);
375     
376     Annotation[] anns1;
377     Annotation[] anns2;
378         
379     anns1 = new Annotation[] { ssH, ssE, ssS};
380     anns2 = new Annotation[] { ssH, ssE, ssE, ssS};    
381     
382     AlignmentAnnotation ann1 = new AlignmentAnnotation("Secondary Structure",
383             "Secondary Structure", anns1);
384     AlignmentAnnotation ann2 = new AlignmentAnnotation("Secondary Structure",
385             "Secondary Structure", anns2);
386     
387     s1.addAlignmentAnnotation(ann1);
388     s2.addAlignmentAnnotation(ann2);    
389         
390     AlignmentI al = new Alignment(new SequenceI[] { s1, s2 });
391     AlignFrame af = new AlignFrame(al, 300, 300);
392     af.setShowSeqFeatures(true);
393     af.getFeatureRenderer().findAllFeatures(true);
394     return af;
395   }
396
397 }