JAL-2399 JAL-2400 tidy Text Colour wording, behaviour including Cancel
[jalview.git] / test / jalview / datamodel / HiddenSequencesTest.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.datamodel;
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.assertNotSame;
27 import static org.testng.AssertJUnit.assertNull;
28 import static org.testng.AssertJUnit.assertSame;
29 import static org.testng.AssertJUnit.assertTrue;
30 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
31
32 import jalview.gui.AlignViewport;
33 import jalview.gui.JvOptionPane;
34
35 import java.util.List;
36
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.BeforeTest;
39 import org.testng.annotations.Test;
40
41 @Test(singleThreaded = true)
42 public class HiddenSequencesTest
43 {
44
45   @BeforeClass(alwaysRun = true)
46   public void setUpJvOptionPane()
47   {
48     JvOptionPane.setInteractiveMode(false);
49     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
50   }
51
52   static int SEQ_COUNT = 10;
53
54   SequenceI[] seqs;
55
56   /**
57    * Set up an alignment of 10 sequences
58    */
59   @BeforeTest(alwaysRun = true)
60   public void setUp()
61   {
62     seqs = new SequenceI[SEQ_COUNT];
63     for (int i = 0; i < SEQ_COUNT; i++)
64     {
65       // sequence lengths are 1, 2, ... 10
66       seqs[i] = new Sequence("Seq" + i, "abcdefghijk".substring(0, i + 1));
67     }
68   }
69
70   /**
71    * Test the method that converts sequence alignment index to what it would be
72    * if all sequences were unhidden
73    */
74   @Test(groups = "Functional")
75   public void testAdjustForHiddenSeqs()
76   {
77     AlignmentI al = new Alignment(seqs);
78     HiddenSequences hs = al.getHiddenSequences();
79     for (int i = 0; i < SEQ_COUNT; i++)
80     {
81       assertEquals(i, hs.adjustForHiddenSeqs(i));
82     }
83
84     // hide seq1 and seq5 and seq6
85     hs.hideSequence(seqs[1]);
86     hs.hideSequence(seqs[5]);
87     hs.hideSequence(seqs[6]);
88
89     /*
90      * alignment is now seq0/2/3/4/7/8/9
91      */
92     assertEquals(7, al.getHeight());
93     assertEquals(0, hs.adjustForHiddenSeqs(0));
94     assertEquals(2, hs.adjustForHiddenSeqs(1));
95     assertEquals(3, hs.adjustForHiddenSeqs(2));
96     assertEquals(4, hs.adjustForHiddenSeqs(3));
97     assertEquals(7, hs.adjustForHiddenSeqs(4));
98     assertEquals(8, hs.adjustForHiddenSeqs(5));
99     assertEquals(9, hs.adjustForHiddenSeqs(6));
100   }
101
102   /**
103    * Test the method that increments the internal array size if a sequence is
104    * added to the alignment (ugh this should not be exposed to the light of day)
105    */
106   @Test(groups = "Functional")
107   public void testAdjustHeightSequenceAdded()
108   {
109     AlignmentI al = new Alignment(seqs);
110     assertEquals(SEQ_COUNT, al.getHeight());
111
112     HiddenSequences hs = al.getHiddenSequences();
113     // initially does nothing
114     hs.adjustHeightSequenceAdded();
115     assertNull(hs.hiddenSequences);
116
117     // hide one sequence
118     hs.hideSequence(seqs[3]);
119     assertEquals(1, hs.getSize());
120     assertEquals(SEQ_COUNT - 1, al.getHeight());
121     assertEquals(SEQ_COUNT, hs.hiddenSequences.length);
122
123     /*
124      * add a sequence to the alignment
125      * - the safe way to call hs.adjustHeightSequenceAdded!
126      * (implementation depends on alignment height having
127      * been already updated for the added sequence)
128      */
129     al.addSequence(new Sequence("a", "b"));
130     assertEquals(1, hs.getSize());
131     assertEquals(SEQ_COUNT, al.getHeight());
132     assertEquals(SEQ_COUNT + 1, hs.hiddenSequences.length);
133   }
134
135   /**
136    * Test the method that decrements the internal array size if a sequence is
137    * deleted from the alignment (ugh this should not be exposed to the light of
138    * day)
139    */
140   @Test(groups = "Functional")
141   public void testAdjustHeightSequenceDeleted()
142   {
143     AlignmentI al = new Alignment(seqs);
144     assertEquals(SEQ_COUNT, al.getHeight());
145
146     HiddenSequences hs = al.getHiddenSequences();
147     // initially does nothing
148     hs.adjustHeightSequenceAdded();
149     assertNull(hs.hiddenSequences);
150
151     // hide two sequences
152     hs.hideSequence(seqs[3]);
153     hs.hideSequence(seqs[5]);
154     assertEquals(2, hs.getSize());
155     assertTrue(hs.isHidden(seqs[3]));
156     assertTrue(hs.isHidden(seqs[5]));
157     assertEquals(SEQ_COUNT - 2, al.getHeight());
158     assertEquals(SEQ_COUNT, hs.hiddenSequences.length);
159
160     /*
161      * delete a visible sequence from the alignment
162      * - the safe way to call hs.adjustHeightSequenceDeleted!
163      * (implementation depends on alignment height having
164      * been already updated for the removed sequence)
165      */
166     al.deleteSequence(seqs[2]);
167     assertEquals(2, hs.getSize());
168     // the visible alignment is unchanged:
169     assertEquals(SEQ_COUNT - 3, al.getHeight());
170     // sequences array size has decremented:
171     assertEquals(SEQ_COUNT - 1, hs.hiddenSequences.length);
172   }
173
174   /**
175    * Test the method that converts a 'full alignment' sequence index into the
176    * equivalent in the alignment with sequences hidden
177    */
178   @Test(groups = "Functional")
179   public void testFindIndexWithoutHiddenSeqs()
180   {
181     AlignmentI al = new Alignment(seqs);
182     HiddenSequences hs = al.getHiddenSequences();
183     for (int i = 0; i < SEQ_COUNT; i++)
184     {
185       assertEquals(i, hs.findIndexWithoutHiddenSeqs(i));
186     }
187
188     // hide seq1 and seq5 and seq6
189     hs.hideSequence(seqs[1]);
190     hs.hideSequence(seqs[5]);
191     hs.hideSequence(seqs[6]);
192
193     /*
194      * alignment is now seq0/2/3/4/7/8/9
195      */
196     assertEquals(7, al.getHeight());
197     assertEquals(0, hs.findIndexWithoutHiddenSeqs(0));
198     assertEquals(0, hs.findIndexWithoutHiddenSeqs(1));
199     assertEquals(1, hs.findIndexWithoutHiddenSeqs(2));
200     assertEquals(2, hs.findIndexWithoutHiddenSeqs(3));
201     assertEquals(3, hs.findIndexWithoutHiddenSeqs(4));
202     assertEquals(3, hs.findIndexWithoutHiddenSeqs(5));
203     assertEquals(3, hs.findIndexWithoutHiddenSeqs(6));
204     assertEquals(4, hs.findIndexWithoutHiddenSeqs(7));
205     assertEquals(5, hs.findIndexWithoutHiddenSeqs(8));
206     assertEquals(6, hs.findIndexWithoutHiddenSeqs(9));
207   }
208
209   /**
210    * Test the method that reconstructs (sort of) the full alignment including
211    * hidden sequences
212    */
213   @Test(groups = "Functional")
214   public void testGetFullAlignment()
215   {
216     AlignmentI al = new Alignment(seqs);
217     assertArrayEquals(seqs, al.getSequencesArray());
218     al.setProperty("a", "b");
219     al.addAnnotation(new AlignmentAnnotation("ann", "label", 12f));
220     al.setSeqrep(seqs[4]);
221     SequenceGroup sg = new SequenceGroup();
222     sg.addSequence(seqs[8], false);
223     al.addGroup(sg);
224     ((Alignment) al).hasRNAStructure = true;
225
226     HiddenSequences hs = al.getHiddenSequences();
227     AlignmentI al2 = hs.getFullAlignment();
228     // new alignment but with original sequences
229     assertNotSame(al, al2);
230     assertArrayEquals(al.getSequencesArray(), al2.getSequencesArray());
231
232     hs.hideSequence(seqs[4]);
233     hs.hideSequence(seqs[9]);
234     al2 = hs.getFullAlignment();
235     assertNotSame(al, al2);
236     assertArrayEquals(seqs, al2.getSequencesArray());
237     assertNotNull(al2.getProperties());
238     assertSame(al.getProperties(), al2.getProperties());
239     assertNotNull(al2.getAlignmentAnnotation());
240     assertSame(al.getAlignmentAnnotation(), al2.getAlignmentAnnotation());
241     assertSame(seqs[4], al2.getSeqrep());
242     assertNotNull(al2.getGroups());
243     assertSame(al.getGroups(), al2.getGroups());
244     assertTrue(al2.hasRNAStructure());
245   }
246
247   /**
248    * Test the method that returns the hidden sequence at a given index in the
249    * full alignment
250    * 
251    * @return either the sequence (if hidden) or null (if not hidden)
252    */
253   @Test(groups = "Functional")
254   public void testGetHiddenSequence()
255   {
256     AlignmentI al = new Alignment(seqs);
257     HiddenSequences hs = al.getHiddenSequences();
258     assertNull(hs.getHiddenSequence(0));
259     hs.hideSequence(seqs[3]);
260     assertSame(seqs[3], hs.getHiddenSequence(3));
261     assertNull(hs.getHiddenSequence(2));
262     assertNull(hs.getHiddenSequence(4));
263   }
264
265   @Test(groups = "Functional")
266   public void testGetSize()
267   {
268   }
269
270   @Test(groups = "Functional")
271   public void testGetWidth()
272   {
273     AlignmentI al = new Alignment(seqs);
274     HiddenSequences hs = al.getHiddenSequences();
275     assertEquals(0, hs.getWidth());
276     hs.hideSequence(seqs[6]);
277     hs.hideSequence(seqs[8]);
278     assertEquals(9, hs.getWidth());
279   }
280
281   /**
282    * Test the method that adds a sequence to the hidden sequences and deletes it
283    * from the alignment, and its converse
284    */
285   @Test(groups = "Functional")
286   public void testHideShowSequence()
287   {
288     AlignmentI al = new Alignment(seqs);
289     assertTrue(al.getSequences().contains(seqs[1]));
290     HiddenSequences hs = al.getHiddenSequences();
291     assertEquals(0, hs.getSize());
292     assertEquals(10, al.getHeight());
293
294     /*
295      * hide the second sequence in the alignment
296      */
297     hs.hideSequence(seqs[1]);
298     assertFalse(hs.isHidden(seqs[0]));
299     assertTrue(hs.isHidden(seqs[1]));
300     assertFalse(al.getSequences().contains(seqs[1]));
301     assertEquals(1, hs.getSize());
302     assertEquals(9, al.getHeight());
303     assertSame(seqs[2], al.getSequenceAt(1));
304
305     /*
306      * hide what is now the second sequence in the alignment
307      */
308     hs.hideSequence(seqs[2]);
309     assertFalse(hs.isHidden(seqs[0]));
310     assertTrue(hs.isHidden(seqs[1]));
311     assertTrue(hs.isHidden(seqs[2]));
312     assertFalse(al.getSequences().contains(seqs[1]));
313     assertFalse(al.getSequences().contains(seqs[2]));
314     assertEquals(2, hs.getSize());
315     assertEquals(8, al.getHeight());
316
317     /*
318      * perform 'reveal' on what is now the second sequence in the alignment
319      * this should unhide the two sequences that precede it
320      */
321     List<SequenceI> revealed = hs.showSequence(1, null);
322     assertEquals(2, revealed.size());
323     assertTrue(revealed.contains(seqs[1]));
324     assertTrue(revealed.contains(seqs[2]));
325     assertEquals(0, hs.getSize());
326     assertEquals(10, al.getHeight());
327   }
328
329   @Test(groups = "Functional")
330   public void testIsHidden()
331   {
332     AlignmentI al = new Alignment(seqs);
333     HiddenSequences hs = al.getHiddenSequences();
334     hs.hideSequence(seqs[7]);
335     hs.hideSequence(seqs[4]);
336     assertTrue(hs.isHidden(seqs[4]));
337     assertFalse(hs.isHidden(seqs[5]));
338     assertFalse(hs.isHidden(seqs[6]));
339     assertTrue(hs.isHidden(seqs[7]));
340     assertFalse(hs.isHidden(null));
341     assertFalse(hs.isHidden(new Sequence("", "")));
342   }
343
344   /**
345    * Test hiding and unhiding a group with a representative sequence. The
346    * representative should be left visible when the group is hidden, and
347    * included in the selected group when it is unhidden.
348    */
349   @Test(groups = "Functional")
350   public void testHideShowSequence_withHiddenRepSequence()
351   {
352     AlignmentI al = new Alignment(seqs);
353
354     /*
355      * represent seqs 2-4 with seq3
356      * this hides seq2 and seq4 but not seq3
357      */
358     AlignViewport av = new AlignViewport(al);
359     SequenceGroup sg = new SequenceGroup();
360     sg.addSequence(seqs[1], false);
361     sg.addSequence(seqs[2], false);
362     sg.addSequence(seqs[3], false);
363     av.setSelectionGroup(sg);
364
365     /*
366      * hiding group with reference sequence is done via AlignViewport
367      */
368     av.hideSequences(seqs[2], true);
369     HiddenSequences hs = al.getHiddenSequences();
370     assertEquals(2, hs.getSize());
371     assertTrue(hs.isHidden(seqs[1]));
372     assertFalse(hs.isHidden(seqs[2]));
373     assertTrue(hs.isHidden(seqs[3]));
374
375     /*
376      * should now be no sequences selected in the alignment
377      */
378     assertNull(av.getSelectionGroup());
379
380     /*
381      * visible alignment is now seq0/2/4/5/6/7/8/9
382      * 'reveal sequences' at the representative sequence (index = 1)
383      * this should unhide the one above i.e. seq1
384      * and return a selection list including seq2
385      * 
386      * note have to call via AlignViewport to get the expected
387      * resulting sequence selection
388      */
389     av.showSequence(1);
390
391     /*
392      * only seq3 is now hidden
393      */
394     assertEquals(1, hs.getSize());
395     assertTrue(hs.isHidden(seqs[3]));
396     assertEquals(SEQ_COUNT - 1, al.getHeight());
397     sg = av.getSelectionGroup();
398
399     /*
400      * unhidden and representative sequence selected
401      * (this behaviour may change! JAL-2133)
402      */
403     assertEquals(2, sg.getSize());
404     assertTrue(sg.getSequences().contains(seqs[1]));
405     assertTrue(sg.getSequences().contains(seqs[2]));
406     assertFalse(sg.getSequences().contains(seqs[3]));
407   }
408 }