JAL-2385 more tests/bug fixes mostly for gui.SliderPanel and some
[jalview.git] / test / jalview / gui / AlignViewportTest.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.gui;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertNotNull;
26 import static org.testng.AssertJUnit.assertSame;
27 import static org.testng.AssertJUnit.assertTrue;
28
29 import jalview.bin.Cache;
30 import jalview.bin.Jalview;
31 import jalview.datamodel.AlignedCodonFrame;
32 import jalview.datamodel.Alignment;
33 import jalview.datamodel.AlignmentAnnotation;
34 import jalview.datamodel.AlignmentI;
35 import jalview.datamodel.Annotation;
36 import jalview.datamodel.PDBEntry;
37 import jalview.datamodel.PDBEntry.Type;
38 import jalview.datamodel.SearchResults;
39 import jalview.datamodel.SearchResultsI;
40 import jalview.datamodel.Sequence;
41 import jalview.datamodel.SequenceI;
42 import jalview.io.DataSourceType;
43 import jalview.io.FileLoader;
44 import jalview.schemes.ColourSchemeI;
45 import jalview.schemes.PIDColourScheme;
46 import jalview.structure.StructureSelectionManager;
47 import jalview.util.MapList;
48
49 import java.util.ArrayList;
50 import java.util.List;
51
52 import org.testng.annotations.BeforeClass;
53 import org.testng.annotations.BeforeMethod;
54 import org.testng.annotations.Test;
55
56 public class AlignViewportTest
57 {
58
59   @BeforeClass(alwaysRun = true)
60   public void setUpJvOptionPane()
61   {
62     JvOptionPane.setInteractiveMode(false);
63     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
64   }
65
66   AlignmentI al;
67
68   AlignViewport testee;
69
70   @BeforeClass(alwaysRun = true)
71   public static void setUpBeforeClass() throws Exception
72   {
73     Jalview.main(new String[] { "-nonews", "-props",
74         "test/jalview/testProps.jvprops" });
75   }
76
77   @BeforeMethod(alwaysRun = true)
78   public void setUp()
79   {
80     SequenceI seq1 = new Sequence("Seq1", "ABC");
81     SequenceI seq2 = new Sequence("Seq2", "ABC");
82     SequenceI seq3 = new Sequence("Seq3", "ABC");
83     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3 };
84     al = new Alignment(seqs);
85     al.setDataset(null);
86     testee = new AlignViewport(al);
87   }
88
89   @Test(groups = { "Functional" })
90   public void testCollateForPdb()
91   {
92     // JBP: What behaviour is this supposed to test ?
93     /*
94      * Set up sequence pdb ids
95      */
96     PDBEntry pdb1 = new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb");
97     PDBEntry pdb2 = new PDBEntry("2ABC", "C", Type.PDB, "2ABC.pdb");
98     PDBEntry pdb3 = new PDBEntry("3ABC", "D", Type.PDB, "3ABC.pdb");
99
100     /*
101      * seq1 and seq3 refer to 1abcB, seq2 to 2abcC, none to 3abcD
102      */
103     al.getSequenceAt(0).getDatasetSequence()
104             .addPDBId(new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb"));
105     al.getSequenceAt(2).getDatasetSequence()
106             .addPDBId(new PDBEntry("1ABC", "B", Type.PDB, "1ABC.pdb"));
107     al.getSequenceAt(1).getDatasetSequence()
108             .addPDBId(new PDBEntry("2ABC", "C", Type.PDB, "2ABC.pdb"));
109     /*
110      * Add a second chain PDB xref to Seq2 - should not result in a duplicate in
111      * the results
112      */
113     al.getSequenceAt(1).getDatasetSequence()
114             .addPDBId(new PDBEntry("2ABC", "D", Type.PDB, "2ABC.pdb"));
115     /*
116      * Seq3 refers to 3abc - this does not match 3ABC (as the code stands)
117      */
118     al.getSequenceAt(2).getDatasetSequence()
119             .addPDBId(new PDBEntry("3abc", "D", Type.PDB, "3ABC.pdb"));
120
121     /*
122      * run method under test
123      */
124     SequenceI[][] seqs = testee.collateForPDB(new PDBEntry[] { pdb1, pdb2,
125         pdb3 });
126
127     // seq1 and seq3 refer to PDBEntry[0]
128     assertEquals(2, seqs[0].length);
129     assertSame(al.getSequenceAt(0), seqs[0][0]);
130     assertSame(al.getSequenceAt(2), seqs[0][1]);
131
132     // seq2 refers to PDBEntry[1]
133     assertEquals(1, seqs[1].length);
134     assertSame(al.getSequenceAt(1), seqs[1][0]);
135
136     // no sequence refers to PDBEntry[2]
137     assertEquals(0, seqs[2].length);
138   }
139
140   /**
141    * Test that a mapping is not deregistered when a second view is closed but
142    * the first still holds a reference to the mapping
143    */
144   @Test(groups = { "Functional" })
145   public void testDeregisterMapping_onCloseView()
146   {
147     /*
148      * alignment with reference to mappings
149      */
150     AlignFrame af1 = new FileLoader().LoadFileWaitTillLoaded(
151             ">Seq1\nCAGT\n", DataSourceType.PASTE);
152
153     SequenceI s1 = af1.getViewport().getAlignment().getSequenceAt(0);
154     AlignedCodonFrame acf1 = new AlignedCodonFrame();
155     acf1.addMap(s1, s1, new MapList(new int[] { 1, 4 }, new int[] { 1, 4 },
156             1, 1));
157     AlignedCodonFrame acf2 = new AlignedCodonFrame();
158     acf2.addMap(s1, s1, new MapList(new int[] { 1, 4 }, new int[] { 4, 1 },
159             1, 1));
160
161     List<AlignedCodonFrame> mappings = new ArrayList<AlignedCodonFrame>();
162     mappings.add(acf1);
163     mappings.add(acf2);
164     af1.getViewport().getAlignment().setCodonFrames(mappings);
165     af1.newView_actionPerformed(null);
166
167     /*
168      * Verify that creating the alignment for the new View has registered the
169      * mappings
170      */
171     StructureSelectionManager ssm = StructureSelectionManager
172             .getStructureSelectionManager(Desktop.instance);
173     assertEquals(2, ssm.getSequenceMappings().size());
174     assertTrue(ssm.getSequenceMappings().contains(acf1));
175     assertTrue(ssm.getSequenceMappings().contains(acf2));
176
177     /*
178      * Close the second view. Verify that mappings are not removed as the first
179      * view still holds a reference to them.
180      */
181     af1.closeMenuItem_actionPerformed(false);
182     assertEquals(2, ssm.getSequenceMappings().size());
183     assertTrue(ssm.getSequenceMappings().contains(acf1));
184     assertTrue(ssm.getSequenceMappings().contains(acf2));
185   }
186
187   /**
188    * Test that a mapping is deregistered if no alignment holds a reference to it
189    */
190   @Test(groups = { "Functional" })
191   public void testDeregisterMapping_withNoReference()
192   {
193     Desktop d = Desktop.instance;
194     assertNotNull(d);
195     StructureSelectionManager ssm = StructureSelectionManager
196             .getStructureSelectionManager(Desktop.instance);
197     ssm.resetAll();
198
199     AlignFrame af1 = new FileLoader().LoadFileWaitTillLoaded(
200             ">Seq1\nRSVQ\n", DataSourceType.PASTE);
201     AlignFrame af2 = new FileLoader().LoadFileWaitTillLoaded(
202             ">Seq2\nDGEL\n", DataSourceType.PASTE);
203     SequenceI cs1 = new Sequence("cseq1", "CCCGGGTTTAAA");
204     SequenceI cs2 = new Sequence("cseq2", "CTTGAGTCTAGA");
205     SequenceI s1 = af1.getViewport().getAlignment().getSequenceAt(0);
206     SequenceI s2 = af2.getViewport().getAlignment().getSequenceAt(0);
207     // need to be distinct
208     AlignedCodonFrame acf1 = new AlignedCodonFrame();
209     acf1.addMap(cs1, s1, new MapList(new int[] { 1, 4 },
210             new int[] { 1, 12 }, 1, 3));
211     AlignedCodonFrame acf2 = new AlignedCodonFrame();
212     acf2.addMap(cs2, s2, new MapList(new int[] { 1, 4 },
213             new int[] { 1, 12 }, 1, 3));
214     AlignedCodonFrame acf3 = new AlignedCodonFrame();
215     acf3.addMap(cs2, cs2, new MapList(new int[] { 1, 12 }, new int[] { 1,
216         12 }, 1, 1));
217
218     List<AlignedCodonFrame> mappings1 = new ArrayList<AlignedCodonFrame>();
219     mappings1.add(acf1);
220     af1.getViewport().getAlignment().setCodonFrames(mappings1);
221
222     List<AlignedCodonFrame> mappings2 = new ArrayList<AlignedCodonFrame>();
223     mappings2.add(acf2);
224     mappings2.add(acf3);
225     af2.getViewport().getAlignment().setCodonFrames(mappings2);
226
227     /*
228      * AlignFrame1 has mapping acf1, AlignFrame2 has acf2 and acf3
229      */
230
231     List<AlignedCodonFrame> ssmMappings = ssm.getSequenceMappings();
232     assertEquals(0, ssmMappings.size());
233     ssm.registerMapping(acf1);
234     assertEquals(1, ssmMappings.size());
235     ssm.registerMapping(acf2);
236     assertEquals(2, ssmMappings.size());
237     ssm.registerMapping(acf3);
238     assertEquals(3, ssmMappings.size());
239
240     /*
241      * Closing AlignFrame2 should remove its mappings from
242      * StructureSelectionManager, since AlignFrame1 has no reference to them
243      */
244     af2.closeMenuItem_actionPerformed(true);
245     assertEquals(1, ssmMappings.size());
246     assertTrue(ssmMappings.contains(acf1));
247   }
248
249   /**
250    * Test that a mapping is not deregistered if another alignment holds a
251    * reference to it
252    */
253   @Test(groups = { "Functional" })
254   public void testDeregisterMapping_withReference()
255   {
256     Desktop d = Desktop.instance;
257     assertNotNull(d);
258     StructureSelectionManager ssm = StructureSelectionManager
259             .getStructureSelectionManager(Desktop.instance);
260     ssm.resetAll();
261
262     AlignFrame af1 = new FileLoader().LoadFileWaitTillLoaded(
263             ">Seq1\nRSVQ\n", DataSourceType.PASTE);
264     AlignFrame af2 = new FileLoader().LoadFileWaitTillLoaded(
265             ">Seq2\nDGEL\n", DataSourceType.PASTE);
266     SequenceI cs1 = new Sequence("cseq1", "CCCGGGTTTAAA");
267     SequenceI cs2 = new Sequence("cseq2", "CTTGAGTCTAGA");
268     SequenceI s1 = af1.getViewport().getAlignment().getSequenceAt(0);
269     SequenceI s2 = af2.getViewport().getAlignment().getSequenceAt(0);
270     // need to be distinct
271     AlignedCodonFrame acf1 = new AlignedCodonFrame();
272     acf1.addMap(cs1, s1, new MapList(new int[] { 1, 4 },
273             new int[] { 1, 12 }, 1, 3));
274     AlignedCodonFrame acf2 = new AlignedCodonFrame();
275     acf2.addMap(cs2, s2, new MapList(new int[] { 1, 4 },
276             new int[] { 1, 12 }, 1, 3));
277     AlignedCodonFrame acf3 = new AlignedCodonFrame();
278     acf3.addMap(cs2, cs2, new MapList(new int[] { 1, 12 }, new int[] { 1,
279         12 }, 1, 1));
280
281     List<AlignedCodonFrame> mappings1 = new ArrayList<AlignedCodonFrame>();
282     mappings1.add(acf1);
283     mappings1.add(acf2);
284     af1.getViewport().getAlignment().setCodonFrames(mappings1);
285
286     List<AlignedCodonFrame> mappings2 = new ArrayList<AlignedCodonFrame>();
287     mappings2.add(acf2);
288     mappings2.add(acf3);
289     af2.getViewport().getAlignment().setCodonFrames(mappings2);
290
291     /*
292      * AlignFrame1 has mappings acf1 and acf2, AlignFrame2 has acf2 and acf3
293      */
294
295     List<AlignedCodonFrame> ssmMappings = ssm.getSequenceMappings();
296     assertEquals(0, ssmMappings.size());
297     ssm.registerMapping(acf1);
298     assertEquals(1, ssmMappings.size());
299     ssm.registerMapping(acf2);
300     assertEquals(2, ssmMappings.size());
301     ssm.registerMapping(acf3);
302     assertEquals(3, ssmMappings.size());
303
304     /*
305      * Closing AlignFrame2 should remove mapping acf3 from
306      * StructureSelectionManager, but not acf2, since AlignFrame1 still has a
307      * reference to it
308      */
309     af2.closeMenuItem_actionPerformed(true);
310     assertEquals(2, ssmMappings.size());
311     assertTrue(ssmMappings.contains(acf1));
312     assertTrue(ssmMappings.contains(acf2));
313     assertFalse(ssmMappings.contains(acf3));
314   }
315
316   /**
317    * Test for JAL-1306 - conservation thread should run even when only Quality
318    * (and not Conservation) is enabled in Preferences
319    */
320   @Test(groups = { "Functional" })
321   public void testUpdateConservation_qualityOnly()
322   {
323     Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS",
324             Boolean.TRUE.toString());
325     Cache.applicationProperties.setProperty("SHOW_QUALITY",
326             Boolean.TRUE.toString());
327     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
328             Boolean.FALSE.toString());
329     Cache.applicationProperties.setProperty("SHOW_IDENTITY",
330             Boolean.FALSE.toString());
331     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
332             "examples/uniref50.fa", DataSourceType.FILE);
333     AlignmentAnnotation[] anns = af.viewport.getAlignment()
334             .getAlignmentAnnotation();
335     assertNotNull("No annotations found", anns);
336     assertEquals("More than one annotation found", 1, anns.length);
337     assertTrue("Annotation is not Quality",
338             anns[0].description.startsWith("Alignment Quality"));
339     Annotation[] annotations = anns[0].annotations;
340     assertNotNull("Quality annotations are null", annotations);
341     assertNotNull("Quality in column 1 is null", annotations[0]);
342     assertTrue("No quality value in column 1", annotations[0].value > 10f);
343   }
344
345   @Test(groups = { "Functional" })
346   public void testSetGlobalColourScheme()
347   {
348     /*
349      * test for JAL-2283: don't inadvertently turn on colour by conservation
350      */
351     Cache.applicationProperties.setProperty("DEFAULT_COLOUR_PROT", "None");
352     Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
353             Boolean.TRUE.toString());
354     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
355             "examples/uniref50.fa", DataSourceType.FILE);
356     ColourSchemeI cs = new PIDColourScheme();
357     af.getViewport().setGlobalColourScheme(cs);
358     assertFalse(af.getViewport().getViewportColourScheme()
359             .conservationApplied());
360   }
361
362   @Test(groups = { "Functional" })
363   public void testSetGetHasSearchResults()
364   {
365     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
366             "examples/uniref50.fa", DataSourceType.FILE);
367     SearchResultsI sr = new SearchResults();
368     SequenceI s1 = af.getViewport().getAlignment().getSequenceAt(0);
369
370     // create arbitrary range on first sequence
371     sr.addResult(s1, s1.getStart() + 10, s1.getStart() + 15);
372
373     // test set
374     af.getViewport().setSearchResults(sr);
375     // has -> true
376     assertTrue(af.getViewport().hasSearchResults());
377     // get == original
378     assertEquals(sr, af.getViewport().getSearchResults());
379
380     // set(null) results in has -> false
381
382     af.getViewport().setSearchResults(null);
383     assertFalse(af.getViewport().hasSearchResults());
384   }
385 }