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 for (int i = 0; i < SEQ_COUNT; i++)
186 assertEquals(i, hs.findIndexWithoutHiddenSeqs(i));
189 // hide seq1 and seq5 and seq6
190 hs.hideSequence(seqs[1]);
191 hs.hideSequence(seqs[5]);
192 hs.hideSequence(seqs[6]);
195 * alignment is now seq0/2/3/4/7/8/9
197 assertEquals(SEQ_COUNT - 3, al.getHeight());
198 assertEquals(0, hs.findIndexWithoutHiddenSeqs(0));
199 assertEquals(0, hs.findIndexWithoutHiddenSeqs(1));
200 assertEquals(1, hs.findIndexWithoutHiddenSeqs(2));
201 assertEquals(2, hs.findIndexWithoutHiddenSeqs(3));
202 assertEquals(3, hs.findIndexWithoutHiddenSeqs(4));
203 assertEquals(3, hs.findIndexWithoutHiddenSeqs(5));
204 assertEquals(3, hs.findIndexWithoutHiddenSeqs(6));
205 assertEquals(4, hs.findIndexWithoutHiddenSeqs(7));
206 assertEquals(5, hs.findIndexWithoutHiddenSeqs(8));
207 assertEquals(6, hs.findIndexWithoutHiddenSeqs(9));
211 * Test the method that finds the visible row position a given distance before
214 @Test(groups = { "Functional" })
215 public void testFindIndexNFromRow()
217 AlignmentI al = new Alignment(seqs);
218 HiddenSequences hs = new HiddenSequences(al);
220 // test that without hidden rows, findIndexNFromRow returns
221 // position n above provided position
222 int pos = hs.subtractVisibleRows(3, 10);
223 assertEquals(7, pos);
225 // 0 returns same position
226 pos = hs.subtractVisibleRows(0, 10);
227 assertEquals(10, pos);
229 // overflow to top returns negative number
230 pos = hs.subtractVisibleRows(3, 0);
231 assertEquals(-3, pos);
233 // test that with hidden rows above result row
234 // behaviour is the same as above
235 hs.hideSequence(seqs[1]);
236 hs.hideSequence(seqs[2]);
237 hs.hideSequence(seqs[3]);
239 // position n above provided position
240 pos = hs.subtractVisibleRows(3, 10);
241 assertEquals(7, pos);
243 // 0 returns same position
244 pos = hs.subtractVisibleRows(0, 10);
245 assertEquals(10, pos);
247 // test with one set of hidden rows between start and required position
248 hs.hideSequence(seqs[12]);
249 hs.hideSequence(seqs[13]);
250 hs.hideSequence(seqs[14]);
251 hs.hideSequence(seqs[15]);
252 pos = hs.subtractVisibleRows(8, 17);
253 assertEquals(5, pos);
255 // test with two sets of hidden rows between start and required position
256 hs.hideSequence(seqs[20]);
257 hs.hideSequence(seqs[21]);
258 pos = hs.subtractVisibleRows(8, 23);
259 assertEquals(9, pos);
261 // repeat last 2 tests with no hidden columns to left of required position
264 // test with one set of hidden rows between start and required position
265 hs.hideSequence(seqs[12]);
266 hs.hideSequence(seqs[13]);
267 hs.hideSequence(seqs[14]);
268 hs.hideSequence(seqs[15]);
269 pos = hs.subtractVisibleRows(8, 17);
270 assertEquals(5, pos);
272 // test with two sets of hidden rows between start and required position
273 hs.hideSequence(seqs[20]);
274 hs.hideSequence(seqs[21]);
275 pos = hs.subtractVisibleRows(8, 23);
276 assertEquals(9, pos);
281 * Test the method that reconstructs (sort of) the full alignment including
284 @Test(groups = "Functional")
285 public void testGetFullAlignment()
287 AlignmentI al = new Alignment(seqs);
288 assertArrayEquals(seqs, al.getSequencesArray());
289 al.setProperty("a", "b");
290 al.addAnnotation(new AlignmentAnnotation("ann", "label", 12f));
291 al.setSeqrep(seqs[4]);
292 SequenceGroup sg = new SequenceGroup();
293 sg.addSequence(seqs[8], false);
295 ((Alignment) al).hasRNAStructure = true;
297 HiddenSequences hs = al.getHiddenSequences();
298 AlignmentI al2 = hs.getFullAlignment();
299 // new alignment but with original sequences
300 assertNotSame(al, al2);
301 assertArrayEquals(al.getSequencesArray(), al2.getSequencesArray());
303 hs.hideSequence(seqs[4]);
304 hs.hideSequence(seqs[9]);
305 al2 = hs.getFullAlignment();
306 assertNotSame(al, al2);
307 assertArrayEquals(seqs, al2.getSequencesArray());
308 assertNotNull(al2.getProperties());
309 assertSame(al.getProperties(), al2.getProperties());
310 assertNotNull(al2.getAlignmentAnnotation());
311 assertSame(al.getAlignmentAnnotation(), al2.getAlignmentAnnotation());
312 assertSame(seqs[4], al2.getSeqrep());
313 assertNotNull(al2.getGroups());
314 assertSame(al.getGroups(), al2.getGroups());
315 assertTrue(al2.hasRNAStructure());
319 * Test the method that returns the hidden sequence at a given index in the
322 * @return either the sequence (if hidden) or null (if not hidden)
324 @Test(groups = "Functional")
325 public void testGetHiddenSequence()
327 AlignmentI al = new Alignment(seqs);
328 HiddenSequences hs = al.getHiddenSequences();
329 assertNull(hs.getHiddenSequence(0));
330 hs.hideSequence(seqs[3]);
331 assertSame(seqs[3], hs.getHiddenSequence(3));
332 assertNull(hs.getHiddenSequence(2));
333 assertNull(hs.getHiddenSequence(4));
336 @Test(groups = "Functional")
337 public void testGetSize()
341 @Test(groups = "Functional")
342 public void testGetWidth()
344 AlignmentI al = new Alignment(seqs);
345 HiddenSequences hs = al.getHiddenSequences();
346 assertEquals(0, hs.getWidth());
347 hs.hideSequence(seqs[6]);
348 hs.hideSequence(seqs[8]);
349 assertEquals(9, hs.getWidth());
353 * Test the method that adds a sequence to the hidden sequences and deletes it
354 * from the alignment, and its converse
356 @Test(groups = "Functional")
357 public void testHideShowSequence()
359 AlignmentI al = new Alignment(seqs);
360 assertTrue(al.getSequences().contains(seqs[1]));
361 HiddenSequences hs = al.getHiddenSequences();
362 assertEquals(0, hs.getSize());
363 assertEquals(SEQ_COUNT, al.getHeight());
366 * hide the second sequence in the alignment
368 hs.hideSequence(seqs[1]);
369 assertFalse(hs.isHidden(seqs[0]));
370 assertTrue(hs.isHidden(seqs[1]));
371 assertFalse(al.getSequences().contains(seqs[1]));
372 assertEquals(1, hs.getSize());
373 assertEquals(SEQ_COUNT - 1, al.getHeight());
374 assertSame(seqs[2], al.getSequenceAt(1));
377 * hide what is now the second sequence in the alignment
379 hs.hideSequence(seqs[2]);
380 assertFalse(hs.isHidden(seqs[0]));
381 assertTrue(hs.isHidden(seqs[1]));
382 assertTrue(hs.isHidden(seqs[2]));
383 assertFalse(al.getSequences().contains(seqs[1]));
384 assertFalse(al.getSequences().contains(seqs[2]));
385 assertEquals(2, hs.getSize());
386 assertEquals(SEQ_COUNT - 2, al.getHeight());
389 * perform 'reveal' on what is now the second sequence in the alignment
390 * this should unhide the two sequences that precede it
392 List<SequenceI> revealed = hs.showSequence(1, null);
393 assertEquals(2, revealed.size());
394 assertTrue(revealed.contains(seqs[1]));
395 assertTrue(revealed.contains(seqs[2]));
396 assertEquals(0, hs.getSize());
397 assertEquals(SEQ_COUNT, al.getHeight());
401 * Test the method that adds a sequence to the hidden sequences and deletes it
402 * from the alignment, and its converse, where the first hidden sequences are
403 * at the bottom of the alignment (JAL-2437)
405 @Test(groups = "Functional")
406 public void testHideShowLastSequences()
408 AlignmentI al = new Alignment(seqs);
409 assertTrue(al.getSequences().contains(seqs[1]));
410 HiddenSequences hs = al.getHiddenSequences();
411 assertEquals(0, hs.getSize());
412 assertEquals(SEQ_COUNT, al.getHeight());
415 * hide the last sequence in the alignment
417 hs.hideSequence(seqs[SEQ_COUNT - 1]);
418 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
419 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 1]));
420 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 1]));
421 assertEquals(1, hs.getSize());
422 assertEquals(SEQ_COUNT - 1, al.getHeight());
425 * hide the third last sequence in the alignment
427 hs.hideSequence(seqs[SEQ_COUNT - 3]);
428 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2]));
429 assertTrue(hs.isHidden(seqs[SEQ_COUNT - 3]));
430 assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 3]));
431 assertEquals(2, hs.getSize());
432 assertEquals(SEQ_COUNT - 2, al.getHeight());
435 * reveal all the sequences, which should be reinstated in the same order as they started in
438 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 3]));
439 assertFalse(hs.isHidden(seqs[SEQ_COUNT - 1]));
440 assertEquals(seqs[SEQ_COUNT - 3], al.getSequences().get(SEQ_COUNT - 3));
441 assertEquals(seqs[SEQ_COUNT - 2], al.getSequences().get(SEQ_COUNT - 2));
442 assertEquals(seqs[SEQ_COUNT - 1], al.getSequences().get(SEQ_COUNT - 1));
443 assertEquals(0, hs.getSize());
444 assertEquals(SEQ_COUNT, al.getHeight());
447 @Test(groups = "Functional")
448 public void testIsHidden()
450 AlignmentI al = new Alignment(seqs);
451 HiddenSequences hs = al.getHiddenSequences();
452 hs.hideSequence(seqs[7]);
453 hs.hideSequence(seqs[4]);
454 assertTrue(hs.isHidden(seqs[4]));
455 assertFalse(hs.isHidden(seqs[5]));
456 assertFalse(hs.isHidden(seqs[6]));
457 assertTrue(hs.isHidden(seqs[7]));
458 assertFalse(hs.isHidden(null));
459 assertFalse(hs.isHidden(new Sequence("", "")));
463 * Test hiding and unhiding a group with a representative sequence. The
464 * representative should be left visible when the group is hidden, and
465 * included in the selected group when it is unhidden.
467 @Test(groups = "Functional")
468 public void testHideShowSequence_withHiddenRepSequence()
470 AlignmentI al = new Alignment(seqs);
473 * represent seqs 2-4 with seq3
474 * this hides seq2 and seq4 but not seq3
476 AlignViewport av = new AlignViewport(al);
477 SequenceGroup sg = new SequenceGroup();
478 sg.addSequence(seqs[1], false);
479 sg.addSequence(seqs[2], false);
480 sg.addSequence(seqs[3], false);
481 av.setSelectionGroup(sg);
484 * hiding group with reference sequence is done via AlignViewport
486 av.hideSequences(seqs[2], true);
487 HiddenSequences hs = al.getHiddenSequences();
488 assertEquals(2, hs.getSize());
489 assertTrue(hs.isHidden(seqs[1]));
490 assertFalse(hs.isHidden(seqs[2]));
491 assertTrue(hs.isHidden(seqs[3]));
494 * should now be no sequences selected in the alignment
496 assertNull(av.getSelectionGroup());
499 * visible alignment is now seq0/2/4/5/6/7/8/9
500 * 'reveal sequences' at the representative sequence (index = 1)
501 * this should unhide the one above i.e. seq1
502 * and return a selection list including seq2
504 * note have to call via AlignViewport to get the expected
505 * resulting sequence selection
510 * only seq3 is now hidden
512 assertEquals(1, hs.getSize());
513 assertTrue(hs.isHidden(seqs[3]));
514 assertEquals(SEQ_COUNT - 1, al.getHeight());
515 sg = av.getSelectionGroup();
518 * unhidden and representative sequence selected
519 * (this behaviour may change! JAL-2133)
521 assertEquals(2, sg.getSize());
522 assertTrue(sg.getSequences().contains(seqs[1]));
523 assertTrue(sg.getSequences().contains(seqs[2]));
524 assertFalse(sg.getSequences().contains(seqs[3]));