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.assertNotSame;
26 import static org.testng.AssertJUnit.assertSame;
27 import static org.testng.AssertJUnit.assertTrue;
29 import java.util.Arrays;
30 import java.util.BitSet;
31 import java.util.List;
33 import org.testng.annotations.Test;
35 public class ColumnSelectionTest
38 @Test(groups = { "Functional" })
39 public void testAddElement()
41 ColumnSelection cs = new ColumnSelection();
45 cs.addElement(5); // ignored
46 List<Integer> sel = cs.getSelected();
47 assertEquals("[2, 5, 3]", sel.toString());
51 * Test the remove method - in particular to verify that remove(int i) removes
52 * the element whose value is i, _NOT_ the i'th element.
54 @Test(groups = { "Functional" })
55 public void testRemoveElement()
57 ColumnSelection cs = new ColumnSelection();
61 // removing elements not in the list has no effect
64 List<Integer> sel = cs.getSelected();
65 assertEquals(2, sel.size());
66 assertEquals(new Integer(2), sel.get(0));
67 assertEquals(new Integer(5), sel.get(1));
69 // removing an element in the list removes it
71 // ...but not from the copy list!
72 assertEquals(2, sel.size());
73 sel = cs.getSelected();
74 assertEquals(1, sel.size());
75 assertEquals(new Integer(5), sel.get(0));
79 * Test the method that finds the visible column position of an alignment
80 * column, allowing for hidden columns.
82 @Test(groups = { "Functional" })
83 public void testFindColumnPosition()
85 ColumnSelection cs = new ColumnSelection();
86 assertEquals(5, cs.findColumnPosition(5));
88 // hiding column 6 makes no difference
90 assertEquals(5, cs.findColumnPosition(5));
92 // hiding column 4 moves column 5 to column 4
94 assertEquals(4, cs.findColumnPosition(5));
96 // hiding columns 1 and 2 moves column 5 to column 2
98 assertEquals(2, cs.findColumnPosition(5));
102 * Test the code used to locate the reference sequence ruler origin
104 @Test(groups = { "Functional" })
105 public void testLocateVisibleBoundsofSequence()
107 ColumnSelection cs = new ColumnSelection();
108 SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
109 assertEquals(2, seq.findIndex(seq.getStart()));
113 Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
114 seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
115 seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
116 seq.findIndex(seq.getEnd()) - 1 }),
117 Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
119 // hidden column on gap after end of sequence - should not affect bounds
122 Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
123 seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
124 seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
125 seq.findIndex(seq.getEnd()) - 1 }),
126 Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
128 cs.revealAllHiddenColumns();
129 // hidden column on gap before beginning of sequence - should vis bounds by
133 Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 2,
134 seq.findIndex(seq.getEnd()) - 2, seq.getStart(),
135 seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
136 seq.findIndex(seq.getEnd()) - 1 }),
137 Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
139 cs.revealAllHiddenColumns();
140 // hide columns around most of sequence - leave one residue remaining
141 cs.hideColumns(1, 3);
142 cs.hideColumns(6, 11);
144 cs.getVisibleSequenceStrings(0, 5, new SequenceI[] { seq })[0]);
146 Arrays.toString(new int[] { 1, 1, 3, 3,
147 seq.findIndex(seq.getStart()) - 1,
148 seq.findIndex(seq.getEnd()) - 1 }),
149 Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
150 cs.revealAllHiddenColumns();
152 // hide whole sequence - should just get location of hidden region
153 // containing sequence
154 cs.hideColumns(1, 11);
156 Arrays.toString(new int[] { 0, 1, 0, 0,
157 seq.findIndex(seq.getStart()) - 1,
158 seq.findIndex(seq.getEnd()) - 1 }),
159 Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
163 @Test(groups={"Functional"})
164 public void testLocateVisibleBoundsPathologicals()
166 // test some pathological cases we missed
167 AlignmentI al = new Alignment(new SequenceI[] { new Sequence("refseqGaptest","KTDVTI----------NFI-----G----L")});
168 ColumnSelection cs = new ColumnSelection();
169 cs.hideInsertionsFor(al.getSequenceAt(0));
173 + al.getSequenceAt(0).getCharAt(
174 cs.adjustForHiddenColumns(9)));
178 @Test(groups = { "Functional" })
179 public void testHideColumns()
181 ColumnSelection cs = new ColumnSelection();
183 List<int[]> hidden = cs.getHiddenColumns();
184 assertEquals(1, hidden.size());
185 assertEquals("[5, 5]", Arrays.toString(hidden.get(0)));
188 assertEquals(2, hidden.size());
189 // two hidden ranges, in order:
190 assertSame(hidden, cs.getHiddenColumns());
191 assertEquals("[3, 3]", Arrays.toString(hidden.get(0)));
192 assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
194 // hiding column 4 expands [3, 3] to [3, 4]
195 // not fancy enough to coalesce this into [3, 5] though
197 hidden = cs.getHiddenColumns();
198 assertEquals(2, hidden.size());
199 assertEquals("[3, 4]", Arrays.toString(hidden.get(0)));
200 assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
202 // clear hidden columns (note they are added to selected)
203 cs.revealAllHiddenColumns();
204 // it is now actually null but getter returns an empty list
205 assertTrue(cs.getHiddenColumns().isEmpty());
207 cs.hideColumns(3, 6);
208 hidden = cs.getHiddenColumns();
209 int[] firstHiddenRange = hidden.get(0);
210 assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
212 // adding a subrange of already hidden should do nothing
213 cs.hideColumns(4, 5);
214 assertEquals(1, hidden.size());
215 assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
216 cs.hideColumns(3, 5);
217 assertEquals(1, hidden.size());
218 assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
219 cs.hideColumns(4, 6);
220 assertEquals(1, hidden.size());
221 assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
222 cs.hideColumns(3, 6);
223 assertEquals(1, hidden.size());
224 assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
226 cs.revealAllHiddenColumns();
227 cs.hideColumns(2, 4);
228 hidden = cs.getHiddenColumns();
229 assertEquals(1, hidden.size());
230 assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
232 // extend contiguous with 2 positions overlap
233 cs.hideColumns(3, 5);
234 assertEquals(1, hidden.size());
235 assertEquals("[2, 5]", Arrays.toString(hidden.get(0)));
237 // extend contiguous with 1 position overlap
238 cs.hideColumns(5, 6);
239 assertEquals(1, hidden.size());
240 assertEquals("[2, 6]", Arrays.toString(hidden.get(0)));
242 // extend contiguous with overlap both ends:
243 cs.hideColumns(1, 7);
244 assertEquals(1, hidden.size());
245 assertEquals("[1, 7]", Arrays.toString(hidden.get(0)));
249 * Test the method that hides a specified column including any adjacent
250 * selected columns. This is a convenience method for the case where multiple
251 * column regions are selected and then hidden using menu option View | Hide |
254 @Test(groups = { "Functional" })
255 public void testHideColumns_withSelection()
257 ColumnSelection cs = new ColumnSelection();
258 // select columns 4-6
262 // hide column 5 (and adjacent):
265 List<int[]> hidden = cs.getHiddenColumns();
266 assertEquals(1, hidden.size());
267 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
268 // none now selected:
269 assertTrue(cs.getSelected().isEmpty());
271 // repeat, hiding column 4 (5 and 6)
272 cs = new ColumnSelection();
277 hidden = cs.getHiddenColumns();
278 assertEquals(1, hidden.size());
279 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
280 assertTrue(cs.getSelected().isEmpty());
282 // repeat, hiding column (4, 5 and) 6
283 cs = new ColumnSelection();
288 hidden = cs.getHiddenColumns();
289 assertEquals(1, hidden.size());
290 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
291 assertTrue(cs.getSelected().isEmpty());
293 // repeat, with _only_ adjacent columns selected
294 cs = new ColumnSelection();
298 hidden = cs.getHiddenColumns();
299 assertEquals(1, hidden.size());
300 assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
301 assertTrue(cs.getSelected().isEmpty());
305 * Test the method that hides all (possibly disjoint) selected column ranges
307 @Test(groups = { "Functional" })
308 public void testHideSelectedColumns()
310 ColumnSelection cs = new ColumnSelection();
311 int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
316 cs.hideColumns(15, 18);
318 cs.hideSelectedColumns();
319 assertTrue(cs.getSelected().isEmpty());
320 List<int[]> hidden = cs.getHiddenColumns();
321 assertEquals(4, hidden.size());
322 assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
323 assertEquals("[7, 9]", Arrays.toString(hidden.get(1)));
324 assertEquals("[15, 18]", Arrays.toString(hidden.get(2)));
325 assertEquals("[20, 22]", Arrays.toString(hidden.get(3)));
329 * Test the method that gets runs of selected columns ordered by column. If
330 * this fails, HideSelectedColumns may also fail
332 @Test(groups = { "Functional" })
333 public void testGetSelectedRanges()
336 * getSelectedRanges returns ordered columns regardless
337 * of the order in which they are added
339 ColumnSelection cs = new ColumnSelection();
340 int[] sel = { 4, 3, 7, 21, 9, 20, 8, 22, 2 };
346 range = cs.getSelectedRanges();
347 assertEquals(3, range.size());
348 assertEquals("[2, 4]", Arrays.toString(range.get(0)));
349 assertEquals("[7, 9]", Arrays.toString(range.get(1)));
350 assertEquals("[20, 22]", Arrays.toString(range.get(2)));
353 range = cs.getSelectedRanges();
354 assertEquals(3, range.size());
355 assertEquals("[0, 4]", Arrays.toString(range.get(0)));
359 * Test the method that reveals a range of hidden columns given the start
360 * column of the range
362 @Test(groups = { "Functional" })
363 public void testRevealHiddenColumns()
365 ColumnSelection cs = new ColumnSelection();
366 cs.hideColumns(5, 8);
368 cs.revealHiddenColumns(5);
369 // hidden columns list now null but getter returns empty list:
370 assertTrue(cs.getHiddenColumns().isEmpty());
371 // revealed columns are marked as selected (added to selection):
372 assertEquals("[10, 5, 6, 7, 8]", cs.getSelected().toString());
374 // calling with a column other than the range start does nothing:
375 cs = new ColumnSelection();
376 cs.hideColumns(5, 8);
377 List<int[]> hidden = cs.getHiddenColumns();
378 cs.revealHiddenColumns(6);
379 assertSame(hidden, cs.getHiddenColumns());
380 assertTrue(cs.getSelected().isEmpty());
383 @Test(groups = { "Functional" })
384 public void testRevealAllHiddenColumns()
386 ColumnSelection cs = new ColumnSelection();
387 cs.hideColumns(5, 8);
388 cs.hideColumns(2, 3);
391 cs.revealAllHiddenColumns();
394 * revealing hidden columns adds them (in order) to the (unordered)
397 assertTrue(cs.getHiddenColumns().isEmpty());
398 assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]", cs.getSelected().toString());
401 @Test(groups = { "Functional" })
402 public void testIsVisible()
404 ColumnSelection cs = new ColumnSelection();
405 cs.hideColumns(2, 4);
406 cs.hideColumns(6, 7);
407 assertTrue(cs.isVisible(0));
408 assertTrue(cs.isVisible(-99));
409 assertTrue(cs.isVisible(1));
410 assertFalse(cs.isVisible(2));
411 assertFalse(cs.isVisible(3));
412 assertFalse(cs.isVisible(4));
413 assertTrue(cs.isVisible(5));
414 assertFalse(cs.isVisible(6));
415 assertFalse(cs.isVisible(7));
418 @Test(groups = { "Functional" })
419 public void testGetVisibleContigs()
421 ColumnSelection cs = new ColumnSelection();
422 cs.hideColumns(3, 6);
423 cs.hideColumns(8, 9);
424 cs.hideColumns(12, 12);
426 // start position is inclusive, end position exclusive:
427 int[] visible = cs.getVisibleContigs(1, 13);
428 assertEquals("[1, 2, 7, 7, 10, 11]", Arrays.toString(visible));
430 visible = cs.getVisibleContigs(4, 14);
431 assertEquals("[7, 7, 10, 11, 13, 13]", Arrays.toString(visible));
433 visible = cs.getVisibleContigs(3, 10);
434 assertEquals("[7, 7]", Arrays.toString(visible));
436 visible = cs.getVisibleContigs(4, 6);
437 assertEquals("[]", Arrays.toString(visible));
440 @Test(groups = { "Functional" })
441 public void testInvertColumnSelection()
443 ColumnSelection cs = new ColumnSelection();
447 cs.hideColumns(3, 3);
448 cs.hideColumns(6, 6);
450 // invert selection from start (inclusive) to end (exclusive)
451 // hidden columns are _not_ changed
452 cs.invertColumnSelection(2, 9);
453 assertEquals("[2, 5, 7]", cs.getSelected().toString());
455 cs.invertColumnSelection(1, 9);
456 assertEquals("[1, 4, 8]", cs.getSelected().toString());
459 @Test(groups = { "Functional" })
460 public void testMaxColumnSelection()
462 ColumnSelection cs = new ColumnSelection();
466 assertEquals(513, cs.getMax());
467 cs.removeElement(513);
468 assertEquals(1, cs.getMax());
470 assertEquals(0, cs.getMax());
473 assertEquals(513, cs.getMax());
477 @Test(groups = { "Functional" })
478 public void testMinColumnSelection()
480 ColumnSelection cs = new ColumnSelection();
484 assertEquals(0, cs.getMin());
486 assertEquals(1, cs.getMin());
488 assertEquals(0, cs.getMin());
491 @Test(groups = { "Functional" })
492 public void testEquals()
494 ColumnSelection cs = new ColumnSelection();
502 // same selections added in a different order
503 ColumnSelection cs2 = new ColumnSelection();
508 // with no hidden columns
509 assertFalse(cs.equals(cs2));
510 assertFalse(cs2.equals(cs));
512 // with hidden columns added in a different order
513 cs2.hideColumns(6, 9);
514 cs2.hideColumns(5, 8);
517 assertTrue(cs.equals(cs2));
518 assertTrue(cs.equals(cs));
519 assertTrue(cs2.equals(cs));
520 assertTrue(cs2.equals(cs2));
523 assertFalse(cs.equals(cs2));
524 assertFalse(cs2.equals(cs));
526 cs2.removeElement(12);
527 assertTrue(cs.equals(cs2));
530 assertFalse(cs.equals(cs2));
532 * unhiding a column adds it to selection!
534 cs2.revealHiddenColumns(88);
535 assertFalse(cs.equals(cs2));
537 assertTrue(cs.equals(cs2));
541 * Test the method that returns selected columns, in the order in which they
544 @Test(groups = { "Functional" })
545 public void testGetSelection()
547 ColumnSelection cs = new ColumnSelection();
548 int[] sel = { 4, 3, 7, 21 };
554 List<Integer> selected1 = cs.getSelected();
555 assertEquals(4, selected1.size());
558 * getSelected returns a copy, verify the list
559 * is externally immutable
562 List<Integer> selected2 = cs.getSelected();
563 assertNotSame(selected1, selected2);
564 assertEquals(4, selected2.size());
568 assertEquals(col, selected2.get(i++).intValue());
575 List<Integer> selected3 = cs.getSelected();
576 assertEquals(3, selected3.size());
577 assertEquals(3, selected3.get(0).intValue());
578 assertEquals(21, selected3.get(1).intValue());
579 assertEquals(1, selected3.get(2).intValue());
582 @Test(groups = "Functional")
583 public void testMarkColumns()
585 ColumnSelection cs = new ColumnSelection();
586 cs.addElement(5); // this will be cleared
587 BitSet toMark = new BitSet();
593 assertTrue(cs.markColumns(toMark, 3, 8, false, false, false));
594 List<Integer> selected = cs.getSelected();
595 assertEquals(2, selected.size());
596 assertTrue(selected.contains(3));
597 assertTrue(selected.contains(6));
600 @Test(groups = "Functional")
601 public void testMarkColumns_extend()
603 ColumnSelection cs = new ColumnSelection();
606 BitSet toMark = new BitSet();
613 * extending selection of {3, 6} should leave {1, 3, 5, 6} selected
615 assertTrue(cs.markColumns(toMark, 3, 8, false, true, false));
616 List<Integer> selected = cs.getSelected();
617 assertEquals(4, selected.size());
618 assertTrue(selected.contains(1));
619 assertTrue(selected.contains(3));
620 assertTrue(selected.contains(5));
621 assertTrue(selected.contains(6));
624 @Test(groups = "Functional")
625 public void testMarkColumns_invert()
627 ColumnSelection cs = new ColumnSelection();
628 cs.addElement(5); // this will be cleared
629 BitSet toMark = new BitSet();
636 * inverted selection of {3, 6} should select {4, 5, 7, 8}
638 assertTrue(cs.markColumns(toMark, 3, 8, true, false, false));
639 List<Integer> selected = cs.getSelected();
640 assertEquals(4, selected.size());
641 assertTrue(selected.contains(4));
642 assertTrue(selected.contains(5));
643 assertTrue(selected.contains(7));
644 assertTrue(selected.contains(8));
647 @Test(groups = "Functional")
648 public void testMarkColumns_toggle()
650 ColumnSelection cs = new ColumnSelection();
651 cs.addElement(1); // outside change range
654 cs.addElement(10); // outside change range
655 BitSet toMark = new BitSet();
662 * toggling state of {3, 6} should leave {1, 4, 6, 10} selected
664 assertTrue(cs.markColumns(toMark, 3, 8, false, false, true));
665 List<Integer> selected = cs.getSelected();
666 assertEquals(4, selected.size());
667 assertTrue(selected.contains(1));
668 assertTrue(selected.contains(4));
669 assertTrue(selected.contains(6));
670 assertTrue(selected.contains(10));