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