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