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;
34 import jalview.viewmodel.AlignmentViewport;
36 import java.util.List;
38 import org.testng.annotations.BeforeClass;
39 import org.testng.annotations.BeforeTest;
40 import org.testng.annotations.Test;
42 @Test(singleThreaded = true)
43 public class HiddenSequencesTest
46 @BeforeClass(alwaysRun = true)
47 public void setUpJvOptionPane()
49 JvOptionPane.setInteractiveMode(false);
50 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
53 static int SEQ_COUNT = 25;
58 * Set up an alignment of 10 sequences
60 @BeforeTest(alwaysRun = true)
63 seqs = new SequenceI[SEQ_COUNT];
64 for (int i = 0; i < SEQ_COUNT; i++)
66 // sequence lengths are 1, 2, ... 25
67 seqs[i] = new Sequence("Seq" + i,
68 "abcdefghijklmnopqrstuvwxy".substring(0, i + 1));
73 * Test the method that converts sequence alignment index to what it would be
74 * if all sequences were unhidden
76 @Test(groups = "Functional")
77 public void testAdjustForHiddenSeqs()
79 AlignmentI al = new Alignment(seqs);
80 HiddenSequences hs = al.getHiddenSequences();
81 for (int i = 0; i < SEQ_COUNT; i++)
83 assertEquals(i, hs.adjustForHiddenSeqs(i));
86 // hide seq1 and seq5 and seq6
87 hs.hideSequence(seqs[1]);
88 hs.hideSequence(seqs[5]);
89 hs.hideSequence(seqs[6]);
92 * alignment is now seq0/2/3/4/7/8/9
94 assertEquals(SEQ_COUNT - 3, al.getHeight());
95 assertEquals(0, hs.adjustForHiddenSeqs(0));
96 assertEquals(2, hs.adjustForHiddenSeqs(1));
97 assertEquals(3, hs.adjustForHiddenSeqs(2));
98 assertEquals(4, hs.adjustForHiddenSeqs(3));
99 assertEquals(7, hs.adjustForHiddenSeqs(4));
100 assertEquals(8, hs.adjustForHiddenSeqs(5));
101 assertEquals(9, hs.adjustForHiddenSeqs(6));
105 * Test the method that increments the internal array size if a sequence is
106 * added to the alignment (ugh this should not be exposed to the light of day)
108 @Test(groups = "Functional")
109 public void testAdjustHeightSequenceAdded()
111 AlignmentI al = new Alignment(seqs);
112 assertEquals(SEQ_COUNT, al.getHeight());
114 HiddenSequences hs = al.getHiddenSequences();
115 // initially does nothing
116 hs.adjustHeightSequenceAdded();
117 assertNull(hs.hiddenSequences);
120 hs.hideSequence(seqs[3]);
121 assertEquals(1, hs.getSize());
122 assertEquals(SEQ_COUNT - 1, al.getHeight());
123 assertEquals(SEQ_COUNT, hs.hiddenSequences.length);
126 * add a sequence to the alignment
127 * - the safe way to call hs.adjustHeightSequenceAdded!
128 * (implementation depends on alignment height having
129 * been already updated for the added sequence)
131 al.addSequence(new Sequence("a", "b"));
132 assertEquals(1, hs.getSize());
133 assertEquals(SEQ_COUNT, al.getHeight());
134 assertEquals(SEQ_COUNT + 1, hs.hiddenSequences.length);
138 * Test the method that decrements the internal array size if a sequence is
139 * deleted from the alignment (ugh this should not be exposed to the light of
142 @Test(groups = "Functional")
143 public void testAdjustHeightSequenceDeleted()
145 AlignmentI al = new Alignment(seqs);
146 assertEquals(SEQ_COUNT, al.getHeight());
148 HiddenSequences hs = al.getHiddenSequences();
149 // initially does nothing
150 hs.adjustHeightSequenceAdded();
151 assertNull(hs.hiddenSequences);
153 // hide two sequences
154 hs.hideSequence(seqs[3]);
155 hs.hideSequence(seqs[5]);
156 assertEquals(2, hs.getSize());
157 assertTrue(hs.isHidden(seqs[3]));
158 assertTrue(hs.isHidden(seqs[5]));
159 assertEquals(SEQ_COUNT - 2, al.getHeight());
160 assertEquals(SEQ_COUNT, hs.hiddenSequences.length);
163 * delete a visible sequence from the alignment
164 * - the safe way to call hs.adjustHeightSequenceDeleted!
165 * (implementation depends on alignment height having
166 * been already updated for the removed sequence)
168 al.deleteSequence(seqs[2]);
169 assertEquals(2, hs.getSize());
170 // the visible alignment is unchanged:
171 assertEquals(SEQ_COUNT - 3, al.getHeight());
172 // sequences array size has decremented:
173 assertEquals(SEQ_COUNT - 1, hs.hiddenSequences.length);
177 * Test the method that converts a 'full alignment' sequence index into the
178 * equivalent in the alignment with sequences hidden
180 @Test(groups = "Functional")
181 public void testFindIndexWithoutHiddenSeqs()
183 AlignmentI al = new Alignment(seqs);
184 HiddenSequences hs = al.getHiddenSequences();
185 int height = al.getHeight();
186 for (int i = 0; i < height; i++)
188 assertEquals(i, hs.findIndexWithoutHiddenSeqs(i));
191 // hide seq1 and seq5 and seq6
192 hs.hideSequence(seqs[1]);
193 hs.hideSequence(seqs[5]);
194 hs.hideSequence(seqs[6]);
197 * alignment is now seq0/2/3/4/7/8/9
199 assertEquals(height - 3, al.getHeight());
200 assertEquals(0, hs.findIndexWithoutHiddenSeqs(0));
201 assertEquals(0, hs.findIndexWithoutHiddenSeqs(1));
202 assertEquals(1, hs.findIndexWithoutHiddenSeqs(2));
203 assertEquals(2, hs.findIndexWithoutHiddenSeqs(3));
204 assertEquals(3, hs.findIndexWithoutHiddenSeqs(4));
205 assertEquals(3, hs.findIndexWithoutHiddenSeqs(5));
206 assertEquals(3, hs.findIndexWithoutHiddenSeqs(6));
207 assertEquals(4, hs.findIndexWithoutHiddenSeqs(7));
208 assertEquals(5, hs.findIndexWithoutHiddenSeqs(8));
209 assertEquals(6, hs.findIndexWithoutHiddenSeqs(9));
212 * hide first two sequences
215 hs.hideSequence(seqs[0]);
216 hs.hideSequence(seqs[1]);
217 assertEquals(-1, hs.findIndexWithoutHiddenSeqs(0));
218 assertEquals(-1, hs.findIndexWithoutHiddenSeqs(1));
219 for (int i = 2; i < height; i++)
221 assertEquals(i - 2, hs.findIndexWithoutHiddenSeqs(i));
226 * Test the method that finds the visible row position a given distance before
229 @Test(groups = { "Functional" })
230 public void testFindIndexNFromRow()
232 AlignmentI al = new Alignment(seqs);
233 HiddenSequences hs = new HiddenSequences(al);
235 // test that without hidden rows, findIndexNFromRow returns
236 // position n above provided position
237 int pos = hs.subtractVisibleRows(3, 10);
238 assertEquals(7, pos);
240 // 0 returns same position
241 pos = hs.subtractVisibleRows(0, 10);
242 assertEquals(10, pos);
244 // overflow to top returns negative number
245 pos = hs.subtractVisibleRows(3, 0);
246 assertEquals(-3, pos);
248 // test that with hidden rows above result row
249 // behaviour is the same as above
250 hs.hideSequence(seqs[1]);
251 hs.hideSequence(seqs[2]);
252 hs.hideSequence(seqs[3]);
254 // position n above provided position
255 pos = hs.subtractVisibleRows(3, 10);
256 assertEquals(7, pos);
258 // 0 returns same position
259 pos = hs.subtractVisibleRows(0, 10);
260 assertEquals(10, pos);
262 // test with one set of hidden rows between start and required position
263 hs.hideSequence(seqs[12]);
264 hs.hideSequence(seqs[13]);
265 hs.hideSequence(seqs[14]);
266 hs.hideSequence(seqs[15]);
267 pos = hs.subtractVisibleRows(8, 17);
268 assertEquals(5, pos);
270 // test with two sets of hidden rows between start and required position
271 hs.hideSequence(seqs[20]);
272 hs.hideSequence(seqs[21]);
273 pos = hs.subtractVisibleRows(8, 23);
274 assertEquals(9, pos);
276 // repeat last 2 tests with no hidden columns to left of required position
279 // test with one set of hidden rows between start and required position
280 hs.hideSequence(seqs[12]);
281 hs.hideSequence(seqs[13]);
282 hs.hideSequence(seqs[14]);
283 hs.hideSequence(seqs[15]);
284 pos = hs.subtractVisibleRows(8, 17);
285 assertEquals(5, pos);
287 // test with two sets of hidden rows between start and required position
288 hs.hideSequence(seqs[20]);
289 hs.hideSequence(seqs[21]);
290 pos = hs.subtractVisibleRows(8, 23);
291 assertEquals(9, pos);
296 * Test the method that reconstructs (sort of) the full alignment including
299 @Test(groups = "Functional")
300 public void testGetFullAlignment()
302 AlignmentI al = new Alignment(seqs);
303 assertArrayEquals(seqs, al.getSequencesArray());
304 al.setProperty("a", "b");
305 al.addAnnotation(new AlignmentAnnotation("ann", "label", 12f));
306 al.setSeqrep(seqs[4]);
307 SequenceGroup sg = new SequenceGroup();
308 sg.addSequence(seqs[8], false);
310 ((Alignment) al).hasRNAStructure = true;
312 HiddenSequences hs = al.getHiddenSequences();
313 AlignmentI al2 = hs.getFullAlignment();
314 // new alignment but with original sequences
315 assertNotSame(al, al2);
316 assertArrayEquals(al.getSequencesArray(), al2.getSequencesArray());
318 hs.hideSequence(seqs[4]);
319 hs.hideSequence(seqs[9]);
320 al2 = hs.getFullAlignment();
321 assertNotSame(al, al2);
322 assertArrayEquals(seqs, al2.getSequencesArray());
323 assertNotNull(al2.getProperties());
324 assertSame(al.getProperties(), al2.getProperties());
325 assertNotNull(al2.getAlignmentAnnotation());
326 assertSame(al.getAlignmentAnnotation(), al2.getAlignmentAnnotation());
327 assertSame(seqs[4], al2.getSeqrep());
328 assertNotNull(al2.getGroups());
329 assertSame(al.getGroups(), al2.getGroups());
330 assertTrue(al2.hasRNAStructure());
334 * Test the method that returns the hidden sequence at a given index in the
337 * @return either the sequence (if hidden) or null (if not hidden)
339 @Test(groups = "Functional")
340 public void testGetHiddenSequence()
342 AlignmentI al = new Alignment(seqs);
343 HiddenSequences hs = al.getHiddenSequences();
344 assertNull(hs.getHiddenSequence(0));
345 hs.hideSequence(seqs[3]);
346 assertSame(seqs[3], hs.getHiddenSequence(3));
347 assertNull(hs.getHiddenSequence(2));
348 assertNull(hs.getHiddenSequence(4));
351 @Test(groups = "Functional")
352 public void testGetSize()
356 @Test(groups = "Functional")
357 public void testGetWidth()
359 AlignmentI al = new Alignment(seqs);
360 HiddenSequences hs = al.getHiddenSequences();
361 assertEquals(0, hs.getWidth());
362 hs.hideSequence(seqs[6]);
363 hs.hideSequence(seqs[8]);
364 assertEquals(9, hs.getWidth());
368 * Test the method that adds a sequence to the hidden sequences and deletes it
369 * from the alignment, and its converse
371 @Test(groups = "Functional")
372 public void testHideShowSequence()
374 AlignmentI al = new Alignment(seqs);
375 assertTrue(al.getSequences().contains(seqs[1]));
376 HiddenSequences hs = al.getHiddenSequences();
377 assertEquals(0, hs.getSize());
378 assertEquals(SEQ_COUNT, al.getHeight());
381 * hide the second sequence in the alignment
383 hs.hideSequence(seqs[1]);
384 assertFalse(hs.isHidden(seqs[0]));
385 assertTrue(hs.isHidden(seqs[1]));
386 assertFalse(al.getSequences().contains(seqs[1]));
387 assertEquals(1, hs.getSize());
388 assertEquals(SEQ_COUNT - 1, al.getHeight());
389 assertSame(seqs[2], al.getSequenceAt(1));
392 * hide what is now the second sequence in the alignment
394 hs.hideSequence(seqs[2]);
395 assertFalse(hs.isHidden(seqs[0]));
396 assertTrue(hs.isHidden(seqs[1]));
397 assertTrue(hs.isHidden(seqs[2]));
398 assertFalse(al.getSequences().contains(seqs[1]));
399 assertFalse(al.getSequences().contains(seqs[2]));
400 assertEquals(2, hs.getSize());
401 assertEquals(SEQ_COUNT - 2, al.getHeight());
404 * perform 'reveal' on what is now the second sequence in the alignment
405 * this should unhide the two sequences that precede it
407 List<SequenceI> revealed = hs.showSequence(1, null);
408 assertEquals(2, revealed.size());
409 assertTrue(revealed.contains(seqs[1]));
410 assertTrue(revealed.contains(seqs[2]));
411 assertEquals(0, hs.getSize());
412 assertEquals(SEQ_COUNT, al.getHeight());
416 * Test the method that adds a sequence to the hidden sequences and deletes it
417 * from the alignment, and its converse, where the first hidden sequences are
418 * at the bottom of the alignment (JAL-2437)
420 @Test(groups = "Functional")
421 public void testHideShowLastSequences()
423 AlignmentI al = new Alignment(seqs);
424 assertTrue(al.getSequences().contains(seqs[1]));
425 HiddenSequences hs = al.getHiddenSequences();
426 assertEquals(0, hs.getSize());
427 assertEquals(SEQ_COUNT, al.getHeight());
430 * hide the last sequence in the alignment
432 hs.hideSequence(seqs[SEQ_COUNT - 1]);
433 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
434 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 1]));
435 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 1]));
436 assertEquals(1, hs.getSize());
437 assertEquals(SEQ_COUNT - 1, al.getHeight());
440 * hide the third last sequence in the alignment
442 hs.hideSequence(seqs[SEQ_COUNT - 3]);
443 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
444 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 3]));
445 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 3]));
446 assertEquals(2, hs.getSize());
447 assertEquals(SEQ_COUNT - 2, al.getHeight());
450 * reveal all the sequences, which should be reinstated in the same order as they started in
453 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 3]));
454 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 1]));
455 assertEquals(seqs[SEQ_COUNT - 3], al.getSequences().get(SEQ_COUNT - 3));
456 assertEquals(seqs[SEQ_COUNT - 2], al.getSequences().get(SEQ_COUNT - 2));
457 assertEquals(seqs[SEQ_COUNT - 1], al.getSequences().get(SEQ_COUNT - 1));
458 assertEquals(0, hs.getSize());
459 assertEquals(SEQ_COUNT, al.getHeight());
462 @Test(groups = "Functional")
463 public void testIsHidden()
465 AlignmentI al = new Alignment(seqs);
466 HiddenSequences hs = al.getHiddenSequences();
467 hs.hideSequence(seqs[7]);
468 hs.hideSequence(seqs[4]);
469 assertTrue(hs.isHidden(seqs[4]));
470 assertFalse(hs.isHidden(seqs[5]));
471 assertFalse(hs.isHidden(seqs[6]));
472 assertTrue(hs.isHidden(seqs[7]));
473 assertFalse(hs.isHidden(null));
474 assertFalse(hs.isHidden(new Sequence("", "")));
478 * Test hiding and unhiding a group with a representative sequence. The
479 * representative should be left visible when the group is hidden, and
480 * included in the selected group when it is unhidden.
482 @Test(groups = "Functional")
483 public void testHideShowSequence_withHiddenRepSequence()
485 AlignmentI al = new Alignment(seqs);
488 * represent seqs 2-4 with seq3
489 * this hides seq2 and seq4 but not seq3
491 AlignmentViewport av = new AlignViewport(al);
492 SequenceGroup sg = new SequenceGroup();
493 sg.addSequence(seqs[1], false);
494 sg.addSequence(seqs[2], false);
495 sg.addSequence(seqs[3], false);
496 av.setSelectionGroup(sg);
499 * hiding group with reference sequence is done via AlignViewport
501 av.hideSequences(seqs[2], true);
502 HiddenSequences hs = al.getHiddenSequences();
503 assertEquals(2, hs.getSize());
504 assertTrue(hs.isHidden(seqs[1]));
505 assertFalse(hs.isHidden(seqs[2]));
506 assertTrue(hs.isHidden(seqs[3]));
509 * should now be no sequences selected in the alignment
511 assertNull(av.getSelectionGroup());
514 * visible alignment is now seq0/2/4/5/6/7/8/9
515 * 'reveal sequences' at the representative sequence (index = 1)
516 * this should unhide the one above i.e. seq1
517 * and return a selection list including seq2
519 * note have to call via AlignViewport to get the expected
520 * resulting sequence selection
525 * only seq3 is now hidden
527 assertEquals(1, hs.getSize());
528 assertTrue(hs.isHidden(seqs[3]));
529 assertEquals(SEQ_COUNT - 1, al.getHeight());
530 sg = av.getSelectionGroup();
533 * unhidden and representative sequence selected
534 * (this behaviour may change! JAL-2133)
536 assertEquals(2, sg.getSize());
537 assertTrue(sg.getSequences().contains(seqs[1]));
538 assertTrue(sg.getSequences().contains(seqs[2]));
539 assertFalse(sg.getSequences().contains(seqs[3]));