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