2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.datamodel;
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;
32 import jalview.gui.AlignViewport;
33 import jalview.gui.JvOptionPane;
35 import java.util.List;
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.BeforeTest;
39 import org.testng.annotations.Test;
41 @Test(singleThreaded = true)
42 public class HiddenSequencesTest
45 @BeforeClass(alwaysRun = true)
46 public void setUpJvOptionPane()
48 JvOptionPane.setInteractiveMode(false);
49 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
52 static int SEQ_COUNT = 25;
57 * Set up an alignment of 10 sequences
59 @BeforeTest(alwaysRun = true)
62 seqs = new SequenceI[SEQ_COUNT];
63 for (int i = 0; i < SEQ_COUNT; i++)
65 // sequence lengths are 1, 2, ... 25
66 seqs[i] = new Sequence("Seq" + i,
67 "abcdefghijklmnopqrstuvwxy".substring(0, i + 1));
72 * Test the method that converts sequence alignment index to what it would be
73 * if all sequences were unhidden
75 @Test(groups = "Functional")
76 public void testAdjustForHiddenSeqs()
78 AlignmentI al = new Alignment(seqs);
79 HiddenSequences hs = al.getHiddenSequences();
80 for (int i = 0; i < SEQ_COUNT; i++)
82 assertEquals(i, hs.adjustForHiddenSeqs(i));
85 // hide seq1 and seq5 and seq6
86 hs.hideSequence(seqs[1]);
87 hs.hideSequence(seqs[5]);
88 hs.hideSequence(seqs[6]);
91 * alignment is now seq0/2/3/4/7/8/9
93 assertEquals(SEQ_COUNT - 3, al.getHeight());
94 assertEquals(0, hs.adjustForHiddenSeqs(0));
95 assertEquals(2, hs.adjustForHiddenSeqs(1));
96 assertEquals(3, hs.adjustForHiddenSeqs(2));
97 assertEquals(4, hs.adjustForHiddenSeqs(3));
98 assertEquals(7, hs.adjustForHiddenSeqs(4));
99 assertEquals(8, hs.adjustForHiddenSeqs(5));
100 assertEquals(9, hs.adjustForHiddenSeqs(6));
104 * Test the method that increments the internal array size if a sequence is
105 * added to the alignment (ugh this should not be exposed to the light of day)
107 @Test(groups = "Functional")
108 public void testAdjustHeightSequenceAdded()
110 AlignmentI al = new Alignment(seqs);
111 assertEquals(SEQ_COUNT, al.getHeight());
113 HiddenSequences hs = al.getHiddenSequences();
114 // initially does nothing
115 hs.adjustHeightSequenceAdded();
116 assertNull(hs.hiddenSequences);
119 hs.hideSequence(seqs[3]);
120 assertEquals(1, hs.getSize());
121 assertEquals(SEQ_COUNT - 1, al.getHeight());
122 assertEquals(SEQ_COUNT, hs.hiddenSequences.length);
125 * add a sequence to the alignment
126 * - the safe way to call hs.adjustHeightSequenceAdded!
127 * (implementation depends on alignment height having
128 * been already updated for the added sequence)
130 al.addSequence(new Sequence("a", "b"));
131 assertEquals(1, hs.getSize());
132 assertEquals(SEQ_COUNT, al.getHeight());
133 assertEquals(SEQ_COUNT + 1, hs.hiddenSequences.length);
137 * Test the method that decrements the internal array size if a sequence is
138 * deleted from the alignment (ugh this should not be exposed to the light of
141 @Test(groups = "Functional")
142 public void testAdjustHeightSequenceDeleted()
144 AlignmentI al = new Alignment(seqs);
145 assertEquals(SEQ_COUNT, al.getHeight());
147 HiddenSequences hs = al.getHiddenSequences();
148 // initially does nothing
149 hs.adjustHeightSequenceAdded();
150 assertNull(hs.hiddenSequences);
152 // hide two sequences
153 hs.hideSequence(seqs[3]);
154 hs.hideSequence(seqs[5]);
155 assertEquals(2, hs.getSize());
156 assertTrue(hs.isHidden(seqs[3]));
157 assertTrue(hs.isHidden(seqs[5]));
158 assertEquals(SEQ_COUNT - 2, al.getHeight());
159 assertEquals(SEQ_COUNT, hs.hiddenSequences.length);
162 * delete a visible sequence from the alignment
163 * - the safe way to call hs.adjustHeightSequenceDeleted!
164 * (implementation depends on alignment height having
165 * been already updated for the removed sequence)
167 al.deleteSequence(seqs[2]);
168 assertEquals(2, hs.getSize());
169 // the visible alignment is unchanged:
170 assertEquals(SEQ_COUNT - 3, al.getHeight());
171 // sequences array size has decremented:
172 assertEquals(SEQ_COUNT - 1, hs.hiddenSequences.length);
176 * Test the method that converts a 'full alignment' sequence index into the
177 * equivalent in the alignment with sequences hidden
179 @Test(groups = "Functional")
180 public void testFindIndexWithoutHiddenSeqs()
182 AlignmentI al = new Alignment(seqs);
183 HiddenSequences hs = al.getHiddenSequences();
184 int height = al.getHeight();
185 for (int i = 0; i < height; i++)
187 assertEquals(i, hs.findIndexWithoutHiddenSeqs(i));
190 // hide seq1 and seq5 and seq6
191 hs.hideSequence(seqs[1]);
192 hs.hideSequence(seqs[5]);
193 hs.hideSequence(seqs[6]);
196 * alignment is now seq0/2/3/4/7/8/9
198 assertEquals(height - 3, al.getHeight());
199 assertEquals(0, hs.findIndexWithoutHiddenSeqs(0));
200 assertEquals(0, hs.findIndexWithoutHiddenSeqs(1));
201 assertEquals(1, hs.findIndexWithoutHiddenSeqs(2));
202 assertEquals(2, hs.findIndexWithoutHiddenSeqs(3));
203 assertEquals(3, hs.findIndexWithoutHiddenSeqs(4));
204 assertEquals(3, hs.findIndexWithoutHiddenSeqs(5));
205 assertEquals(3, hs.findIndexWithoutHiddenSeqs(6));
206 assertEquals(4, hs.findIndexWithoutHiddenSeqs(7));
207 assertEquals(5, hs.findIndexWithoutHiddenSeqs(8));
208 assertEquals(6, hs.findIndexWithoutHiddenSeqs(9));
211 * hide first sequence only
214 hs.hideSequence(seqs[0]);
215 for (int i = 1; i < height; i++)
217 assertEquals(i - 1, hs.findIndexWithoutHiddenSeqs(i));
219 assertEquals(-1, hs.findIndexWithoutHiddenSeqs(0));
223 * Test the method that finds the visible row position a given distance before
226 @Test(groups = { "Functional" })
227 public void testFindIndexNFromRow()
229 AlignmentI al = new Alignment(seqs);
230 HiddenSequences hs = new HiddenSequences(al);
232 // test that without hidden rows, findIndexNFromRow returns
233 // position n above provided position
234 int pos = hs.subtractVisibleRows(3, 10);
235 assertEquals(7, pos);
237 // 0 returns same position
238 pos = hs.subtractVisibleRows(0, 10);
239 assertEquals(10, pos);
241 // overflow to top returns negative number
242 pos = hs.subtractVisibleRows(3, 0);
243 assertEquals(-3, pos);
245 // test that with hidden rows above result row
246 // behaviour is the same as above
247 hs.hideSequence(seqs[1]);
248 hs.hideSequence(seqs[2]);
249 hs.hideSequence(seqs[3]);
251 // position n above provided position
252 pos = hs.subtractVisibleRows(3, 10);
253 assertEquals(7, pos);
255 // 0 returns same position
256 pos = hs.subtractVisibleRows(0, 10);
257 assertEquals(10, pos);
259 // test with one set of hidden rows between start and required position
260 hs.hideSequence(seqs[12]);
261 hs.hideSequence(seqs[13]);
262 hs.hideSequence(seqs[14]);
263 hs.hideSequence(seqs[15]);
264 pos = hs.subtractVisibleRows(8, 17);
265 assertEquals(5, pos);
267 // test with two sets of hidden rows between start and required position
268 hs.hideSequence(seqs[20]);
269 hs.hideSequence(seqs[21]);
270 pos = hs.subtractVisibleRows(8, 23);
271 assertEquals(9, pos);
273 // repeat last 2 tests with no hidden columns to left of required position
276 // test with one set of hidden rows between start and required position
277 hs.hideSequence(seqs[12]);
278 hs.hideSequence(seqs[13]);
279 hs.hideSequence(seqs[14]);
280 hs.hideSequence(seqs[15]);
281 pos = hs.subtractVisibleRows(8, 17);
282 assertEquals(5, pos);
284 // test with two sets of hidden rows between start and required position
285 hs.hideSequence(seqs[20]);
286 hs.hideSequence(seqs[21]);
287 pos = hs.subtractVisibleRows(8, 23);
288 assertEquals(9, pos);
293 * Test the method that reconstructs (sort of) the full alignment including
296 @Test(groups = "Functional")
297 public void testGetFullAlignment()
299 AlignmentI al = new Alignment(seqs);
300 assertArrayEquals(seqs, al.getSequencesArray());
301 al.setProperty("a", "b");
302 al.addAnnotation(new AlignmentAnnotation("ann", "label", 12f));
303 al.setSeqrep(seqs[4]);
304 SequenceGroup sg = new SequenceGroup();
305 sg.addSequence(seqs[8], false);
307 ((Alignment) al).hasRNAStructure = true;
309 HiddenSequences hs = al.getHiddenSequences();
310 AlignmentI al2 = hs.getFullAlignment();
311 // new alignment but with original sequences
312 assertNotSame(al, al2);
313 assertArrayEquals(al.getSequencesArray(), al2.getSequencesArray());
315 hs.hideSequence(seqs[4]);
316 hs.hideSequence(seqs[9]);
317 al2 = hs.getFullAlignment();
318 assertNotSame(al, al2);
319 assertArrayEquals(seqs, al2.getSequencesArray());
320 assertNotNull(al2.getProperties());
321 assertSame(al.getProperties(), al2.getProperties());
322 assertNotNull(al2.getAlignmentAnnotation());
323 assertSame(al.getAlignmentAnnotation(), al2.getAlignmentAnnotation());
324 assertSame(seqs[4], al2.getSeqrep());
325 assertNotNull(al2.getGroups());
326 assertSame(al.getGroups(), al2.getGroups());
327 assertTrue(al2.hasRNAStructure());
331 * Test the method that returns the hidden sequence at a given index in the
334 * @return either the sequence (if hidden) or null (if not hidden)
336 @Test(groups = "Functional")
337 public void testGetHiddenSequence()
339 AlignmentI al = new Alignment(seqs);
340 HiddenSequences hs = al.getHiddenSequences();
341 assertNull(hs.getHiddenSequence(0));
342 hs.hideSequence(seqs[3]);
343 assertSame(seqs[3], hs.getHiddenSequence(3));
344 assertNull(hs.getHiddenSequence(2));
345 assertNull(hs.getHiddenSequence(4));
348 @Test(groups = "Functional")
349 public void testGetSize()
353 @Test(groups = "Functional")
354 public void testGetWidth()
356 AlignmentI al = new Alignment(seqs);
357 HiddenSequences hs = al.getHiddenSequences();
358 assertEquals(0, hs.getWidth());
359 hs.hideSequence(seqs[6]);
360 hs.hideSequence(seqs[8]);
361 assertEquals(9, hs.getWidth());
365 * Test the method that adds a sequence to the hidden sequences and deletes it
366 * from the alignment, and its converse
368 @Test(groups = "Functional")
369 public void testHideShowSequence()
371 AlignmentI al = new Alignment(seqs);
372 assertTrue(al.getSequences().contains(seqs[1]));
373 HiddenSequences hs = al.getHiddenSequences();
374 assertEquals(0, hs.getSize());
375 assertEquals(SEQ_COUNT, al.getHeight());
378 * hide the second sequence in the alignment
380 hs.hideSequence(seqs[1]);
381 assertFalse(hs.isHidden(seqs[0]));
382 assertTrue(hs.isHidden(seqs[1]));
383 assertFalse(al.getSequences().contains(seqs[1]));
384 assertEquals(1, hs.getSize());
385 assertEquals(SEQ_COUNT - 1, al.getHeight());
386 assertSame(seqs[2], al.getSequenceAt(1));
389 * hide what is now the second sequence in the alignment
391 hs.hideSequence(seqs[2]);
392 assertFalse(hs.isHidden(seqs[0]));
393 assertTrue(hs.isHidden(seqs[1]));
394 assertTrue(hs.isHidden(seqs[2]));
395 assertFalse(al.getSequences().contains(seqs[1]));
396 assertFalse(al.getSequences().contains(seqs[2]));
397 assertEquals(2, hs.getSize());
398 assertEquals(SEQ_COUNT - 2, al.getHeight());
401 * perform 'reveal' on what is now the second sequence in the alignment
402 * this should unhide the two sequences that precede it
404 List<SequenceI> revealed = hs.showSequence(1, null);
405 assertEquals(2, revealed.size());
406 assertTrue(revealed.contains(seqs[1]));
407 assertTrue(revealed.contains(seqs[2]));
408 assertEquals(0, hs.getSize());
409 assertEquals(SEQ_COUNT, al.getHeight());
413 * Test the method that adds a sequence to the hidden sequences and deletes it
414 * from the alignment, and its converse, where the first hidden sequences are
415 * at the bottom of the alignment (JAL-2437)
417 @Test(groups = "Functional")
418 public void testHideShowLastSequences()
420 AlignmentI al = new Alignment(seqs);
421 assertTrue(al.getSequences().contains(seqs[1]));
422 HiddenSequences hs = al.getHiddenSequences();
423 assertEquals(0, hs.getSize());
424 assertEquals(SEQ_COUNT, al.getHeight());
427 * hide the last sequence in the alignment
429 hs.hideSequence(seqs[SEQ_COUNT - 1]);
430 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
431 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 1]));
432 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 1]));
433 assertEquals(1, hs.getSize());
434 assertEquals(SEQ_COUNT - 1, al.getHeight());
437 * hide the third last sequence in the alignment
439 hs.hideSequence(seqs[SEQ_COUNT - 3]);
440 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
441 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 3]));
442 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 3]));
443 assertEquals(2, hs.getSize());
444 assertEquals(SEQ_COUNT - 2, al.getHeight());
447 * reveal all the sequences, which should be reinstated in the same order as they started in
450 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 3]));
451 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 1]));
452 assertEquals(seqs[SEQ_COUNT - 3], al.getSequences().get(SEQ_COUNT - 3));
453 assertEquals(seqs[SEQ_COUNT - 2], al.getSequences().get(SEQ_COUNT - 2));
454 assertEquals(seqs[SEQ_COUNT - 1], al.getSequences().get(SEQ_COUNT - 1));
455 assertEquals(0, hs.getSize());
456 assertEquals(SEQ_COUNT, al.getHeight());
459 @Test(groups = "Functional")
460 public void testIsHidden()
462 AlignmentI al = new Alignment(seqs);
463 HiddenSequences hs = al.getHiddenSequences();
464 hs.hideSequence(seqs[7]);
465 hs.hideSequence(seqs[4]);
466 assertTrue(hs.isHidden(seqs[4]));
467 assertFalse(hs.isHidden(seqs[5]));
468 assertFalse(hs.isHidden(seqs[6]));
469 assertTrue(hs.isHidden(seqs[7]));
470 assertFalse(hs.isHidden(null));
471 assertFalse(hs.isHidden(new Sequence("", "")));
475 * Test hiding and unhiding a group with a representative sequence. The
476 * representative should be left visible when the group is hidden, and
477 * included in the selected group when it is unhidden.
479 @Test(groups = "Functional")
480 public void testHideShowSequence_withHiddenRepSequence()
482 AlignmentI al = new Alignment(seqs);
485 * represent seqs 2-4 with seq3
486 * this hides seq2 and seq4 but not seq3
488 AlignViewport av = new AlignViewport(al);
489 SequenceGroup sg = new SequenceGroup();
490 sg.addSequence(seqs[1], false);
491 sg.addSequence(seqs[2], false);
492 sg.addSequence(seqs[3], false);
493 av.setSelectionGroup(sg);
496 * hiding group with reference sequence is done via AlignViewport
498 av.hideSequences(seqs[2], true);
499 HiddenSequences hs = al.getHiddenSequences();
500 assertEquals(2, hs.getSize());
501 assertTrue(hs.isHidden(seqs[1]));
502 assertFalse(hs.isHidden(seqs[2]));
503 assertTrue(hs.isHidden(seqs[3]));
506 * should now be no sequences selected in the alignment
508 assertNull(av.getSelectionGroup());
511 * visible alignment is now seq0/2/4/5/6/7/8/9
512 * 'reveal sequences' at the representative sequence (index = 1)
513 * this should unhide the one above i.e. seq1
514 * and return a selection list including seq2
516 * note have to call via AlignViewport to get the expected
517 * resulting sequence selection
522 * only seq3 is now hidden
524 assertEquals(1, hs.getSize());
525 assertTrue(hs.isHidden(seqs[3]));
526 assertEquals(SEQ_COUNT - 1, al.getHeight());
527 sg = av.getSelectionGroup();
530 * unhidden and representative sequence selected
531 * (this behaviour may change! JAL-2133)
533 assertEquals(2, sg.getSize());
534 assertTrue(sg.getSequences().contains(seqs[1]));
535 assertTrue(sg.getSequences().contains(seqs[2]));
536 assertFalse(sg.getSequences().contains(seqs[3]));