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 two sequences
214 hs.hideSequence(seqs[0]);
215 hs.hideSequence(seqs[1]);
216 assertEquals(-1, hs.findIndexWithoutHiddenSeqs(0));
217 assertEquals(-1, hs.findIndexWithoutHiddenSeqs(1));
218 for (int i = 2; i < height; i++)
220 assertEquals(i - 2, hs.findIndexWithoutHiddenSeqs(i));
225 * Test the method that finds the visible row position a given distance before
228 @Test(groups = { "Functional" })
229 public void testFindIndexNFromRow()
231 AlignmentI al = new Alignment(seqs);
232 HiddenSequences hs = new HiddenSequences(al);
234 // test that without hidden rows, findIndexNFromRow returns
235 // position n above provided position
236 int pos = hs.subtractVisibleRows(3, 10);
237 assertEquals(7, pos);
239 // 0 returns same position
240 pos = hs.subtractVisibleRows(0, 10);
241 assertEquals(10, pos);
243 // overflow to top returns negative number
244 pos = hs.subtractVisibleRows(3, 0);
245 assertEquals(-3, pos);
247 // test that with hidden rows above result row
248 // behaviour is the same as above
249 hs.hideSequence(seqs[1]);
250 hs.hideSequence(seqs[2]);
251 hs.hideSequence(seqs[3]);
253 // position n above provided position
254 pos = hs.subtractVisibleRows(3, 10);
255 assertEquals(7, pos);
257 // 0 returns same position
258 pos = hs.subtractVisibleRows(0, 10);
259 assertEquals(10, pos);
261 // test with one set of hidden rows between start and required position
262 hs.hideSequence(seqs[12]);
263 hs.hideSequence(seqs[13]);
264 hs.hideSequence(seqs[14]);
265 hs.hideSequence(seqs[15]);
266 pos = hs.subtractVisibleRows(8, 17);
267 assertEquals(5, pos);
269 // test with two sets of hidden rows between start and required position
270 hs.hideSequence(seqs[20]);
271 hs.hideSequence(seqs[21]);
272 pos = hs.subtractVisibleRows(8, 23);
273 assertEquals(9, pos);
275 // repeat last 2 tests with no hidden columns to left of required position
278 // test with one set of hidden rows between start and required position
279 hs.hideSequence(seqs[12]);
280 hs.hideSequence(seqs[13]);
281 hs.hideSequence(seqs[14]);
282 hs.hideSequence(seqs[15]);
283 pos = hs.subtractVisibleRows(8, 17);
284 assertEquals(5, pos);
286 // test with two sets of hidden rows between start and required position
287 hs.hideSequence(seqs[20]);
288 hs.hideSequence(seqs[21]);
289 pos = hs.subtractVisibleRows(8, 23);
290 assertEquals(9, pos);
295 * Test the method that reconstructs (sort of) the full alignment including
298 @Test(groups = "Functional")
299 public void testGetFullAlignment()
301 AlignmentI al = new Alignment(seqs);
302 assertArrayEquals(seqs, al.getSequencesArray());
303 al.setProperty("a", "b");
304 al.addAnnotation(new AlignmentAnnotation("ann", "label", 12f));
305 al.setSeqrep(seqs[4]);
306 SequenceGroup sg = new SequenceGroup();
307 sg.addSequence(seqs[8], false);
309 ((Alignment) al).hasRNAStructure = true;
311 HiddenSequences hs = al.getHiddenSequences();
312 AlignmentI al2 = hs.getFullAlignment();
313 // new alignment but with original sequences
314 assertNotSame(al, al2);
315 assertArrayEquals(al.getSequencesArray(), al2.getSequencesArray());
317 hs.hideSequence(seqs[4]);
318 hs.hideSequence(seqs[9]);
319 al2 = hs.getFullAlignment();
320 assertNotSame(al, al2);
321 assertArrayEquals(seqs, al2.getSequencesArray());
322 assertNotNull(al2.getProperties());
323 assertSame(al.getProperties(), al2.getProperties());
324 assertNotNull(al2.getAlignmentAnnotation());
325 assertSame(al.getAlignmentAnnotation(), al2.getAlignmentAnnotation());
326 assertSame(seqs[4], al2.getSeqrep());
327 assertNotNull(al2.getGroups());
328 assertSame(al.getGroups(), al2.getGroups());
329 assertTrue(al2.hasRNAStructure());
333 * Test the method that returns the hidden sequence at a given index in the
336 * @return either the sequence (if hidden) or null (if not hidden)
338 @Test(groups = "Functional")
339 public void testGetHiddenSequence()
341 AlignmentI al = new Alignment(seqs);
342 HiddenSequences hs = al.getHiddenSequences();
343 assertNull(hs.getHiddenSequence(0));
344 hs.hideSequence(seqs[3]);
345 assertSame(seqs[3], hs.getHiddenSequence(3));
346 assertNull(hs.getHiddenSequence(2));
347 assertNull(hs.getHiddenSequence(4));
350 @Test(groups = "Functional")
351 public void testGetSize()
355 @Test(groups = "Functional")
356 public void testGetWidth()
358 AlignmentI al = new Alignment(seqs);
359 HiddenSequences hs = al.getHiddenSequences();
360 assertEquals(0, hs.getWidth());
361 hs.hideSequence(seqs[6]);
362 hs.hideSequence(seqs[8]);
363 assertEquals(9, hs.getWidth());
367 * Test the method that adds a sequence to the hidden sequences and deletes it
368 * from the alignment, and its converse
370 @Test(groups = "Functional")
371 public void testHideShowSequence()
373 AlignmentI al = new Alignment(seqs);
374 assertTrue(al.getSequences().contains(seqs[1]));
375 HiddenSequences hs = al.getHiddenSequences();
376 assertEquals(0, hs.getSize());
377 assertEquals(SEQ_COUNT, al.getHeight());
380 * hide the second sequence in the alignment
382 hs.hideSequence(seqs[1]);
383 assertFalse(hs.isHidden(seqs[0]));
384 assertTrue(hs.isHidden(seqs[1]));
385 assertFalse(al.getSequences().contains(seqs[1]));
386 assertEquals(1, hs.getSize());
387 assertEquals(SEQ_COUNT - 1, al.getHeight());
388 assertSame(seqs[2], al.getSequenceAt(1));
391 * hide what is now the second sequence in the alignment
393 hs.hideSequence(seqs[2]);
394 assertFalse(hs.isHidden(seqs[0]));
395 assertTrue(hs.isHidden(seqs[1]));
396 assertTrue(hs.isHidden(seqs[2]));
397 assertFalse(al.getSequences().contains(seqs[1]));
398 assertFalse(al.getSequences().contains(seqs[2]));
399 assertEquals(2, hs.getSize());
400 assertEquals(SEQ_COUNT - 2, al.getHeight());
403 * perform 'reveal' on what is now the second sequence in the alignment
404 * this should unhide the two sequences that precede it
406 List<SequenceI> revealed = hs.showSequence(1, null);
407 assertEquals(2, revealed.size());
408 assertTrue(revealed.contains(seqs[1]));
409 assertTrue(revealed.contains(seqs[2]));
410 assertEquals(0, hs.getSize());
411 assertEquals(SEQ_COUNT, al.getHeight());
415 * Test the method that adds a sequence to the hidden sequences and deletes it
416 * from the alignment, and its converse, where the first hidden sequences are
417 * at the bottom of the alignment (JAL-2437)
419 @Test(groups = "Functional")
420 public void testHideShowLastSequences()
422 AlignmentI al = new Alignment(seqs);
423 assertTrue(al.getSequences().contains(seqs[1]));
424 HiddenSequences hs = al.getHiddenSequences();
425 assertEquals(0, hs.getSize());
426 assertEquals(SEQ_COUNT, al.getHeight());
429 * hide the last sequence in the alignment
431 hs.hideSequence(seqs[SEQ_COUNT - 1]);
432 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
433 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 1]));
434 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 1]));
435 assertEquals(1, hs.getSize());
436 assertEquals(SEQ_COUNT - 1, al.getHeight());
439 * hide the third last sequence in the alignment
441 hs.hideSequence(seqs[SEQ_COUNT - 3]);
442 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
443 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 3]));
444 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 3]));
445 assertEquals(2, hs.getSize());
446 assertEquals(SEQ_COUNT - 2, al.getHeight());
449 * reveal all the sequences, which should be reinstated in the same order as they started in
452 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 3]));
453 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 1]));
454 assertEquals(seqs[SEQ_COUNT - 3], al.getSequences().get(SEQ_COUNT - 3));
455 assertEquals(seqs[SEQ_COUNT - 2], al.getSequences().get(SEQ_COUNT - 2));
456 assertEquals(seqs[SEQ_COUNT - 1], al.getSequences().get(SEQ_COUNT - 1));
457 assertEquals(0, hs.getSize());
458 assertEquals(SEQ_COUNT, al.getHeight());
461 @Test(groups = "Functional")
462 public void testIsHidden()
464 AlignmentI al = new Alignment(seqs);
465 HiddenSequences hs = al.getHiddenSequences();
466 hs.hideSequence(seqs[7]);
467 hs.hideSequence(seqs[4]);
468 assertTrue(hs.isHidden(seqs[4]));
469 assertFalse(hs.isHidden(seqs[5]));
470 assertFalse(hs.isHidden(seqs[6]));
471 assertTrue(hs.isHidden(seqs[7]));
472 assertFalse(hs.isHidden(null));
473 assertFalse(hs.isHidden(new Sequence("", "")));
477 * Test hiding and unhiding a group with a representative sequence. The
478 * representative should be left visible when the group is hidden, and
479 * included in the selected group when it is unhidden.
481 @Test(groups = "Functional")
482 public void testHideShowSequence_withHiddenRepSequence()
484 AlignmentI al = new Alignment(seqs);
487 * represent seqs 2-4 with seq3
488 * this hides seq2 and seq4 but not seq3
490 AlignViewport av = new AlignViewport(al);
491 SequenceGroup sg = new SequenceGroup();
492 sg.addSequence(seqs[1], false);
493 sg.addSequence(seqs[2], false);
494 sg.addSequence(seqs[3], false);
495 av.setSelectionGroup(sg);
498 * hiding group with reference sequence is done via AlignViewport
500 av.hideSequences(seqs[2], true);
501 HiddenSequences hs = al.getHiddenSequences();
502 assertEquals(2, hs.getSize());
503 assertTrue(hs.isHidden(seqs[1]));
504 assertFalse(hs.isHidden(seqs[2]));
505 assertTrue(hs.isHidden(seqs[3]));
508 * should now be no sequences selected in the alignment
510 assertNull(av.getSelectionGroup());
513 * visible alignment is now seq0/2/4/5/6/7/8/9
514 * 'reveal sequences' at the representative sequence (index = 1)
515 * this should unhide the one above i.e. seq1
516 * and return a selection list including seq2
518 * note have to call via AlignViewport to get the expected
519 * resulting sequence selection
524 * only seq3 is now hidden
526 assertEquals(1, hs.getSize());
527 assertTrue(hs.isHidden(seqs[3]));
528 assertEquals(SEQ_COUNT - 1, al.getHeight());
529 sg = av.getSelectionGroup();
532 * unhidden and representative sequence selected
533 * (this behaviour may change! JAL-2133)
535 assertEquals(2, sg.getSize());
536 assertTrue(sg.getSequences().contains(seqs[1]));
537 assertTrue(sg.getSequences().contains(seqs[2]));
538 assertFalse(sg.getSequences().contains(seqs[3]));