JAL-2647 unit test
[jalview.git] / test / jalview / datamodel / HiddenColumnsTest.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
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.
11  *  
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.
16  * 
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.
20  */
21 package jalview.datamodel;
22
23 import static org.testng.Assert.assertNull;
24 import static org.testng.AssertJUnit.assertEquals;
25 import static org.testng.AssertJUnit.assertFalse;
26 import static org.testng.AssertJUnit.assertTrue;
27
28 import jalview.analysis.AlignmentGenerator;
29 import jalview.gui.JvOptionPane;
30 import jalview.util.Comparison;
31
32 import java.util.Arrays;
33 import java.util.BitSet;
34 import java.util.Iterator;
35 import java.util.Random;
36
37 import org.testng.annotations.BeforeClass;
38 import org.testng.annotations.Test;
39
40 public class HiddenColumnsTest
41 {
42
43   @BeforeClass(alwaysRun = true)
44   public void setUpJvOptionPane()
45   {
46     JvOptionPane.setInteractiveMode(false);
47     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
48   }
49
50   /**
51    * Test the method which counts the number of hidden columns
52    */
53   @Test(groups = { "Functional" })
54   public void testGetSize()
55   {
56     HiddenColumns hidden = new HiddenColumns();
57     assertEquals(0, hidden.getSize());
58
59     hidden.hideColumns(3, 5);
60     assertEquals(3, hidden.getSize());
61
62     hidden.hideColumns(8, 8);
63     assertEquals(4, hidden.getSize());
64
65     hidden.hideColumns(9, 14);
66     assertEquals(10, hidden.getSize());
67
68     ColumnSelection cs = new ColumnSelection();
69     hidden.revealAllHiddenColumns(cs);
70     assertEquals(0, hidden.getSize());
71   }
72
73   /**
74    * Test the method that finds the visible column position of an alignment
75    * column, allowing for hidden columns.
76    */
77   @Test(groups = { "Functional" })
78   public void testFindColumnPosition()
79   {
80     HiddenColumns cs = new HiddenColumns();
81     assertEquals(5, cs.findColumnPosition(5));
82
83     // hiding column 6 makes no difference
84     cs.hideColumns(6, 6);
85     assertEquals(5, cs.findColumnPosition(5));
86
87     // hiding column 4 moves column 5 to column 4
88     cs.hideColumns(4, 4);
89     assertEquals(4, cs.findColumnPosition(5));
90
91     // hiding column 4 moves column 4 to position 3
92     assertEquals(3, cs.findColumnPosition(4));
93
94     // hiding columns 1 and 2 moves column 5 to column 2
95     cs.hideColumns(1, 2);
96     assertEquals(2, cs.findColumnPosition(5));
97
98     // check with > 1 hidden column regions
99     // where some columns are in the hidden regions
100     HiddenColumns cs2 = new HiddenColumns();
101     cs2.hideColumns(5, 10);
102     cs2.hideColumns(20, 27);
103     cs2.hideColumns(40, 44);
104
105     // hiding columns 5-10 and 20-27 moves column 8 to column 4
106     assertEquals(4, cs2.findColumnPosition(8));
107
108     // and moves column 24 to 13
109     assertEquals(13, cs2.findColumnPosition(24));
110
111     // and moves column 28 to 14
112     assertEquals(14, cs2.findColumnPosition(28));
113
114     // and moves column 40 to 25
115     assertEquals(25, cs2.findColumnPosition(40));
116
117     // check when hidden columns start at 0 that the visible column
118     // is returned as 0
119     HiddenColumns cs3 = new HiddenColumns();
120     cs3.hideColumns(0, 4);
121     assertEquals(0, cs3.findColumnPosition(2));
122
123   }
124
125   /**
126    * Test the method that finds the visible column position a given distance
127    * before another column
128    */
129   @Test(groups = { "Functional" })
130   public void testFindColumnNToLeft()
131   {
132     HiddenColumns cs = new HiddenColumns();
133
134     // test that without hidden columns, findColumnNToLeft returns
135     // position n to left of provided position
136     long pos = cs.subtractVisibleColumns(3, 10);
137     assertEquals(7, pos);
138
139     // 0 returns same position
140     pos = cs.subtractVisibleColumns(0, 10);
141     assertEquals(10, pos);
142
143     // overflow to left returns negative number
144     pos = cs.subtractVisibleColumns(3, 0);
145     assertEquals(-3, pos);
146
147     // test that with hidden columns to left of result column
148     // behaviour is the same as above
149     cs.hideColumns(1, 3);
150
151     // position n to left of provided position
152     pos = cs.subtractVisibleColumns(3, 10);
153     assertEquals(7, pos);
154
155     // 0 returns same position
156     pos = cs.subtractVisibleColumns(0, 10);
157     assertEquals(10, pos);
158
159     // test with one set of hidden columns between start and required position
160     cs.hideColumns(12, 15);
161     pos = cs.subtractVisibleColumns(8, 17);
162     assertEquals(5, pos);
163
164     // test with two sets of hidden columns between start and required position
165     cs.hideColumns(20, 21);
166     pos = cs.subtractVisibleColumns(8, 23);
167     assertEquals(9, pos);
168
169     // repeat last 2 tests with no hidden columns to left of required position
170     ColumnSelection colsel = new ColumnSelection();
171     cs.revealAllHiddenColumns(colsel);
172
173     // test with one set of hidden columns between start and required position
174     cs.hideColumns(12, 15);
175     pos = cs.subtractVisibleColumns(8, 17);
176     assertEquals(5, pos);
177
178     // test with two sets of hidden columns between start and required position
179     cs.hideColumns(20, 21);
180     pos = cs.subtractVisibleColumns(8, 23);
181     assertEquals(9, pos);
182
183   }
184
185   @Test(groups = { "Functional" })
186   public void testVisibleContigsIterator()
187   {
188     HiddenColumns cs = new HiddenColumns();
189
190     Iterator<int[]> visible = cs.getVisContigsIterator(3, 10);
191     int[] region = visible.next();
192     assertEquals("[3, 9]", Arrays.toString(region));
193     assertFalse(visible.hasNext());
194
195     cs.hideColumns(3, 6);
196     cs.hideColumns(8, 9);
197     cs.hideColumns(12, 12);
198
199     // Test both ends visible region
200
201     // start position is inclusive, end position exclusive
202     visible = cs.getVisContigsIterator(1, 13);
203     region = visible.next();
204     assertEquals("[1, 2]", Arrays.toString(region));
205     region = visible.next();
206     assertEquals("[7, 7]", Arrays.toString(region));
207     region = visible.next();
208     assertEquals("[10, 11]", Arrays.toString(region));
209     assertFalse(visible.hasNext());
210
211     // Test start hidden, end visible
212     visible = cs.getVisContigsIterator(4, 14);
213     region = visible.next();
214     assertEquals("[7, 7]", Arrays.toString(region));
215     region = visible.next();
216     assertEquals("[10, 11]", Arrays.toString(region));
217     region = visible.next();
218     assertEquals("[13, 13]", Arrays.toString(region));
219     assertFalse(visible.hasNext());
220
221     // Test start hidden, end hidden
222     visible = cs.getVisContigsIterator(3, 10);
223     region = visible.next();
224     assertEquals("[7, 7]", Arrays.toString(region));
225     assertFalse(visible.hasNext());
226
227     // Test start visible, end hidden
228     visible = cs.getVisContigsIterator(0, 13);
229     region = visible.next();
230     assertEquals("[0, 2]", Arrays.toString(region));
231     region = visible.next();
232     assertEquals("[7, 7]", Arrays.toString(region));
233     region = visible.next();
234     assertEquals("[10, 11]", Arrays.toString(region));
235     assertFalse(visible.hasNext());
236
237     // Test empty result
238     visible = cs.getVisContigsIterator(4, 6);
239     assertFalse(visible.hasNext());
240   }
241
242   @Test(groups = { "Functional" })
243   public void testEquals()
244   {
245     HiddenColumns cs = new HiddenColumns();
246     cs.hideColumns(5, 9);
247
248     // a different set of hidden columns
249     HiddenColumns cs2 = new HiddenColumns();
250
251     // with no hidden columns
252     assertFalse(cs.equals(cs2));
253     assertFalse(cs2.equals(cs));
254
255     // with hidden columns added in a different order
256     cs2.hideColumns(6, 9);
257     cs2.hideColumns(5, 8);
258
259     assertTrue(cs.equals(cs2));
260     assertTrue(cs.equals(cs));
261     assertTrue(cs2.equals(cs));
262     assertTrue(cs2.equals(cs2));
263   }
264
265   @Test(groups = "Functional")
266   public void testCopyConstructor()
267   {
268     HiddenColumns cs = new HiddenColumns();
269     cs.hideColumns(10, 11);
270     cs.hideColumns(5, 7);
271     Iterator<int[]> regions = cs.iterator();
272     assertEquals("[5, 7]",
273             Arrays.toString(regions.next()));
274
275     HiddenColumns cs2 = new HiddenColumns(cs);
276     regions = cs2.iterator();
277     assertTrue(cs2.hasHiddenColumns());
278     assertEquals(2, cs2.getNumberOfRegions());
279     // hidden columns are held in column order
280     assertEquals("[5, 7]",
281             Arrays.toString(regions.next()));
282     assertEquals("[10, 11]",
283             Arrays.toString(regions.next()));
284   }
285
286   @Test(groups = "Functional")
287   public void testCopyConstructor2()
288   {
289     HiddenColumns cs = new HiddenColumns();
290     cs.hideColumns(10, 11);
291     cs.hideColumns(5, 7);
292
293     HiddenColumns cs2 = new HiddenColumns(cs, 3, 9, 1);
294     assertTrue(cs2.hasHiddenColumns());
295     Iterator<int[]> regions = cs2.iterator();
296
297     // only [5,7] returned, offset by 1
298     assertEquals("[4, 6]",
299             Arrays.toString(regions.next()));
300     assertEquals(3, cs2.getSize());
301
302     cs2 = new HiddenColumns(cs, 8, 15, 4);
303     regions = cs2.iterator();
304     assertTrue(cs2.hasHiddenColumns());
305
306     // only [10,11] returned, offset by 4
307     assertEquals("[6, 7]",
308             Arrays.toString(regions.next()));
309     assertEquals(2, cs2.getSize());
310
311     cs2 = new HiddenColumns(cs, 6, 10, 4);
312     assertFalse(cs2.hasHiddenColumns());
313   }
314
315   /**
316    * Test the code used to locate the reference sequence ruler origin
317    */
318   @Test(groups = { "Functional" })
319   public void testLocateVisibleBoundsofSequence()
320   {
321     // create random alignment
322     AlignmentGenerator gen = new AlignmentGenerator(false);
323     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
324
325     HiddenColumns cs = al.getHiddenColumns();
326     ColumnSelection colsel = new ColumnSelection();
327
328     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
329     assertEquals(2, seq.findIndex(seq.getStart()));
330
331     // no hidden columns
332     assertEquals(
333             Arrays.toString(new int[]
334     { seq.findIndex(seq.getStart()) - 1, seq.findIndex(seq.getStart()) - 1,
335         seq.findIndex(seq.getEnd()) - 1 }),
336             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
337
338     // hidden column on gap after end of sequence - should not affect bounds
339     colsel.hideSelectedColumns(13, al.getHiddenColumns());
340     assertEquals(
341             Arrays.toString(new int[]
342     { seq.findIndex(seq.getStart()) - 1, seq.findIndex(seq.getStart()) - 1,
343         seq.findIndex(seq.getEnd()) - 1 }),
344             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
345
346     cs.revealAllHiddenColumns(colsel);
347     // hidden column on gap before beginning of sequence - should vis bounds by
348     // one
349     colsel.hideSelectedColumns(0, al.getHiddenColumns());
350     assertEquals(
351             Arrays.toString(new int[]
352     { seq.findIndex(seq.getStart()) - 2, seq.findIndex(seq.getStart()) - 1,
353         seq.findIndex(seq.getEnd()) - 1 }),
354             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
355
356     cs.revealAllHiddenColumns(colsel);
357     // hide columns around most of sequence - leave one residue remaining
358     cs.hideColumns(1, 3);
359     cs.hideColumns(6, 11);
360     assertEquals("-D",
361             cs.getVisibleSequenceStrings(0, 5, new SequenceI[]
362     { seq })[0]);
363
364     assertEquals(
365             Arrays.toString(
366                     new int[]
367             { 1, seq.findIndex(seq.getStart()) - 1,
368         seq.findIndex(seq.getEnd()) - 1 }),
369             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
370     cs.revealAllHiddenColumns(colsel);
371
372     // hide whole sequence - should just get location of hidden region
373     // containing sequence
374     cs.hideColumns(1, 11);
375     assertEquals(
376             Arrays.toString(
377                     new int[]
378             { 0, seq.findIndex(seq.getStart()) - 1,
379         seq.findIndex(seq.getEnd()) - 1 }),
380             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
381
382     cs.revealAllHiddenColumns(colsel);
383     cs.hideColumns(0, 15);
384     assertEquals(Arrays
385             .toString(new int[]
386     { 0, seq.findIndex(seq.getStart()) - 1,
387         seq.findIndex(seq.getEnd()) - 1 }),
388             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
389
390     SequenceI seq2 = new Sequence("RefSeq2", "-------A-SD-ASD--E---");
391
392     cs.revealAllHiddenColumns(colsel);
393     cs.hideColumns(7, 17);
394     assertEquals(
395             Arrays.toString(
396                     new int[]
397             { 0, seq2.findIndex(seq2.getStart()) - 1,
398         seq2.findIndex(seq2.getEnd()) - 1 }),
399             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq2)));
400
401     cs.revealAllHiddenColumns(colsel);
402     cs.hideColumns(3, 17);
403     assertEquals(
404             Arrays.toString(
405                     new int[]
406             { 0, seq2.findIndex(seq2.getStart()) - 1,
407         seq2.findIndex(seq2.getEnd()) - 1 }),
408             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq2)));
409
410     cs.revealAllHiddenColumns(colsel);
411     cs.hideColumns(3, 19);
412     assertEquals(
413             Arrays.toString(
414                     new int[]
415             { 0, seq2.findIndex(seq2.getStart()) - 1,
416         seq2.findIndex(seq2.getEnd()) - 1 }),
417             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq2)));
418
419     cs.revealAllHiddenColumns(colsel);
420     cs.hideColumns(0, 0);
421     int[] test = cs.locateVisibleBoundsOfSequence(seq);
422     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
423             Arrays.toString(test));
424
425     cs.revealAllHiddenColumns(colsel);
426     cs.hideColumns(0, 1);
427     test = cs.locateVisibleBoundsOfSequence(seq);
428     assertEquals(Arrays.toString(new int[] { 1, 1, 11 }),
429             Arrays.toString(test));
430
431     cs.revealAllHiddenColumns(colsel);
432     cs.hideColumns(0, 2);
433     test = cs.locateVisibleBoundsOfSequence(seq);
434     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
435             Arrays.toString(test));
436
437     cs.revealAllHiddenColumns(colsel);
438     cs.hideColumns(1, 1);
439     test = cs.locateVisibleBoundsOfSequence(seq);
440     assertEquals(Arrays.toString(new int[] { 2, 1, 11 }),
441             Arrays.toString(test));
442
443     cs.revealAllHiddenColumns(colsel);
444     cs.hideColumns(1, 2);
445     test = cs.locateVisibleBoundsOfSequence(seq);
446     assertEquals(Arrays.toString(new int[] { 1, 1, 11 }),
447             Arrays.toString(test));
448
449     cs.revealAllHiddenColumns(colsel);
450     cs.hideColumns(1, 3);
451     test = cs.locateVisibleBoundsOfSequence(seq);
452     assertEquals(Arrays.toString(new int[] { 1, 1, 11 }),
453             Arrays.toString(test));
454
455     cs.revealAllHiddenColumns(colsel);
456     cs.hideColumns(0, 2);
457     cs.hideColumns(5, 6);
458     test = cs.locateVisibleBoundsOfSequence(seq);
459     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
460             Arrays.toString(test));
461
462     cs.revealAllHiddenColumns(colsel);
463     cs.hideColumns(0, 2);
464     cs.hideColumns(5, 6);
465     cs.hideColumns(9, 10);
466     test = cs.locateVisibleBoundsOfSequence(seq);
467     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
468             Arrays.toString(test));
469
470     cs.revealAllHiddenColumns(colsel);
471     cs.hideColumns(0, 2);
472     cs.hideColumns(7, 11);
473     test = cs.locateVisibleBoundsOfSequence(seq);
474     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
475             Arrays.toString(test));
476
477     cs.revealAllHiddenColumns(colsel);
478     cs.hideColumns(2, 4);
479     cs.hideColumns(7, 11);
480     test = cs.locateVisibleBoundsOfSequence(seq);
481     assertEquals(Arrays.toString(new int[] { 1, 1, 11 }),
482             Arrays.toString(test));
483
484     cs.revealAllHiddenColumns(colsel);
485     cs.hideColumns(2, 4);
486     cs.hideColumns(7, 12);
487     test = cs.locateVisibleBoundsOfSequence(seq);
488     assertEquals(Arrays.toString(new int[] { 1, 1, 11 }),
489             Arrays.toString(test));
490
491     cs.revealAllHiddenColumns(colsel);
492     cs.hideColumns(1, 11);
493     test = cs.locateVisibleBoundsOfSequence(seq);
494     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
495             Arrays.toString(test));
496
497     cs.revealAllHiddenColumns(colsel);
498     cs.hideColumns(0, 12);
499     test = cs.locateVisibleBoundsOfSequence(seq);
500     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
501             Arrays.toString(test));
502
503     cs.revealAllHiddenColumns(colsel);
504     cs.hideColumns(0, 4);
505     cs.hideColumns(6, 12);
506     test = cs.locateVisibleBoundsOfSequence(seq);
507     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
508             Arrays.toString(test));
509
510     cs.revealAllHiddenColumns(colsel);
511     cs.hideColumns(0, 1);
512     cs.hideColumns(3, 12);
513     test = cs.locateVisibleBoundsOfSequence(seq);
514     assertEquals(Arrays.toString(new int[] { 0, 1, 11 }),
515             Arrays.toString(test));
516
517     // These tests cover different behaviour to original
518     // locateVisibleBoundsOfSequence
519     // Previously first values of each were 3,9 and 6 respectively.
520     cs.revealAllHiddenColumns(colsel);
521     cs.hideColumns(3, 14);
522     cs.hideColumns(17, 19);
523     assertEquals(
524             Arrays.toString(
525                     new int[]
526             { 3, seq2.findIndex(seq2.getStart()) - 1,
527         seq2.findIndex(seq2.getEnd()) - 1 }),
528             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq2)));
529
530     cs.revealAllHiddenColumns(colsel);
531     cs.hideColumns(3, 7);
532     cs.hideColumns(9, 14);
533     cs.hideColumns(17, 19);
534     assertEquals(
535             Arrays.toString(
536                     new int[]
537             { 9, seq2.findIndex(seq2.getStart()) - 1,
538         seq2.findIndex(seq2.getEnd()) - 1 }),
539             Arrays.toString(cs.locateVisibleBoundsOfSequence(seq2)));
540
541     cs.revealAllHiddenColumns(colsel);
542     cs.hideColumns(0, 1);
543     cs.hideColumns(3, 4);
544     cs.hideColumns(6, 8);
545     cs.hideColumns(10, 12);
546     test = cs.locateVisibleBoundsOfSequence(seq);
547     assertEquals(Arrays.toString(new int[] { 6, 1, 11 }),
548             Arrays.toString(test));
549
550   }
551
552   @Test(groups = { "Functional" })
553   public void testLocateVisibleBoundsPathologicals()
554   {
555     // test some pathological cases we missed
556     AlignmentI al = new Alignment(
557             new SequenceI[]
558     { new Sequence("refseqGaptest", "KTDVTI----------NFI-----G----L") });
559     HiddenColumns cs = new HiddenColumns();
560     cs.hideInsertionsFor(al.getSequenceAt(0));
561     assertEquals("G", ""
562             + al.getSequenceAt(0).getCharAt(cs.adjustForHiddenColumns(9)));
563
564   }
565
566   @Test(groups = { "Functional" })
567   public void testHideColumns()
568   {
569     // create random alignment
570     AlignmentGenerator gen = new AlignmentGenerator(false);
571     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
572
573     ColumnSelection colsel = new ColumnSelection();
574     HiddenColumns cs = al.getHiddenColumns();
575     colsel.hideSelectedColumns(5, al.getHiddenColumns());
576     Iterator<int[]> regions = cs.iterator();
577     assertEquals(1, cs.getNumberOfRegions());
578     assertEquals("[5, 5]", Arrays.toString(regions.next()));
579
580     colsel.hideSelectedColumns(3, al.getHiddenColumns());
581     regions = cs.iterator();
582     assertEquals(2, cs.getNumberOfRegions());
583     // two hidden ranges, in order:
584     assertEquals("[3, 3]", Arrays.toString(regions.next()));
585     assertEquals("[5, 5]", Arrays.toString(regions.next()));
586
587     // hiding column 4 expands [3, 3] to [3, 4]
588     // and merges to [5, 5] to make [3, 5]
589     colsel.hideSelectedColumns(4, al.getHiddenColumns());
590     regions = cs.iterator();
591     assertEquals(1, cs.getNumberOfRegions());
592     assertEquals("[3, 5]", Arrays.toString(regions.next()));
593
594     // clear hidden columns (note they are added to selected)
595     cs.revealAllHiddenColumns(colsel);
596     // it is now actually null but getter returns an empty list
597     assertEquals(0, cs.getNumberOfRegions());
598
599     cs.hideColumns(3, 6);
600     regions = cs.iterator();
601     int[] firstHiddenRange = regions.next();
602     assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
603
604     // adding a subrange of already hidden should do nothing
605     cs.hideColumns(4, 5);
606     regions = cs.iterator();
607     assertEquals(1, cs.getNumberOfRegions());
608     assertEquals("[3, 6]",
609             Arrays.toString(regions.next()));
610     cs.hideColumns(3, 5);
611     regions = cs.iterator();
612     assertEquals(1, cs.getNumberOfRegions());
613     assertEquals("[3, 6]",
614             Arrays.toString(regions.next()));
615     cs.hideColumns(4, 6);
616     regions = cs.iterator();
617     assertEquals(1, cs.getNumberOfRegions());
618     assertEquals("[3, 6]",
619             Arrays.toString(regions.next()));
620     cs.hideColumns(3, 6);
621     regions = cs.iterator();
622     assertEquals(1, cs.getNumberOfRegions());
623     assertEquals("[3, 6]",
624             Arrays.toString(regions.next()));
625
626     cs.revealAllHiddenColumns(colsel);
627     cs.hideColumns(2, 4);
628     regions = cs.iterator();
629     assertEquals(1, cs.getNumberOfRegions());
630     assertEquals("[2, 4]", Arrays.toString(regions.next()));
631
632     // extend contiguous with 2 positions overlap
633     cs.hideColumns(3, 5);
634     regions = cs.iterator();
635     assertEquals(1, cs.getNumberOfRegions());
636     assertEquals("[2, 5]", Arrays.toString(regions.next()));
637
638     // extend contiguous with 1 position overlap
639     cs.hideColumns(5, 6);
640     regions = cs.iterator();
641     assertEquals(1, cs.getNumberOfRegions());
642     assertEquals("[2, 6]", Arrays.toString(regions.next()));
643
644     // extend contiguous with overlap both ends:
645     cs.hideColumns(1, 7);
646     regions = cs.iterator();
647     assertEquals(1, cs.getNumberOfRegions());
648     assertEquals("[1, 7]", Arrays.toString(regions.next()));
649   }
650
651   /**
652    * Test the method that reveals a range of hidden columns given the start
653    * column of the range
654    */
655   @Test(groups = { "Functional" })
656   public void testRevealHiddenColumns()
657   {
658     ColumnSelection colsel = new ColumnSelection();
659     HiddenColumns cs = new HiddenColumns();
660     cs.hideColumns(5, 8);
661     colsel.addElement(10);
662     cs.revealHiddenColumns(5, colsel);
663
664     // hiddenColumns now empty
665     assertEquals(0, cs.getSize());
666
667     // revealed columns are marked as selected (added to selection):
668     assertEquals("[10, 5, 6, 7, 8]", colsel.getSelected().toString());
669
670     // calling with a column other than the range start does nothing:
671     colsel = new ColumnSelection();
672     cs = new HiddenColumns();
673     cs.hideColumns(5, 8);
674
675     int prevSize = cs.getSize();
676     cs.revealHiddenColumns(6, colsel);
677     assertEquals(prevSize, cs.getSize());
678     assertTrue(colsel.getSelected().isEmpty());
679   }
680
681   @Test(groups = { "Functional" })
682   public void testRevealAllHiddenColumns()
683   {
684     HiddenColumns hidden = new HiddenColumns();
685     ColumnSelection colsel = new ColumnSelection();
686     hidden.hideColumns(5, 8);
687     hidden.hideColumns(2, 3);
688     colsel.addElement(11);
689     colsel.addElement(1);
690     hidden.revealAllHiddenColumns(colsel);
691
692     /*
693      * revealing hidden columns adds them (in order) to the (unordered)
694      * selection list
695      */
696
697     // hiddenColumns now empty
698     assertEquals(0, hidden.getSize());
699
700     assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]",
701             colsel.getSelected().toString());
702   }
703
704   @Test(groups = { "Functional" })
705   public void testIsVisible()
706   {
707     HiddenColumns cs = new HiddenColumns();
708     cs.hideColumns(2, 4);
709     cs.hideColumns(6, 7);
710     assertTrue(cs.isVisible(0));
711     assertTrue(cs.isVisible(-99));
712     assertTrue(cs.isVisible(1));
713     assertFalse(cs.isVisible(2));
714     assertFalse(cs.isVisible(3));
715     assertFalse(cs.isVisible(4));
716     assertTrue(cs.isVisible(5));
717     assertFalse(cs.isVisible(6));
718     assertFalse(cs.isVisible(7));
719   }
720
721   /**
722    * Test for the case when a hidden range encloses more one already hidden
723    * range
724    */
725   @Test(groups = { "Functional" })
726   public void testHideColumns_subsumingHidden()
727   {
728     /*
729      * JAL-2370 bug scenario:
730      * two hidden ranges subsumed by a third
731      */
732     HiddenColumns cs = new HiddenColumns();
733     cs.hideColumns(49, 59);
734     cs.hideColumns(69, 79);
735     Iterator<int[]> regions = cs.iterator();
736     assertEquals(2, cs.getNumberOfRegions());
737     assertEquals("[49, 59]", Arrays.toString(regions.next()));
738     assertEquals("[69, 79]", Arrays.toString(regions.next()));
739
740     cs.hideColumns(48, 80);
741     regions = cs.iterator();
742     assertEquals(1, cs.getNumberOfRegions());
743     assertEquals("[48, 80]", Arrays.toString(regions.next()));
744
745     /*
746      * another...joining hidden ranges
747      */
748     cs = new HiddenColumns();
749     cs.hideColumns(10, 20);
750     cs.hideColumns(30, 40);
751     cs.hideColumns(50, 60);
752     // hiding 21-49 should merge to one range
753     cs.hideColumns(21, 49);
754     regions = cs.iterator();
755     assertEquals(1, cs.getNumberOfRegions());
756     assertEquals("[10, 60]", Arrays.toString(regions.next()));
757
758     /*
759      * another...left overlap, subsumption, right overlap,
760      * no overlap of existing hidden ranges
761      */
762     cs = new HiddenColumns();
763     cs.hideColumns(10, 20);
764     cs.hideColumns(10, 20);
765     cs.hideColumns(30, 35);
766     cs.hideColumns(40, 50);
767     cs.hideColumns(60, 70);
768
769     cs.hideColumns(15, 45);
770     regions = cs.iterator();
771     assertEquals(2, cs.getNumberOfRegions());
772     assertEquals("[10, 50]", Arrays.toString(regions.next()));
773     assertEquals("[60, 70]", Arrays.toString(regions.next()));
774   }
775
776   @Test(groups = { "Functional" })
777   public void testHideBitset()
778   {
779     HiddenColumns cs;
780
781     BitSet one = new BitSet();
782
783     // one hidden range
784     one.set(1);
785     cs = new HiddenColumns();
786     cs.hideMarkedBits(one);
787     assertEquals(1, cs.getNumberOfRegions());
788
789     one.set(2);
790     cs = new HiddenColumns();
791     cs.hideMarkedBits(one);
792     assertEquals(1, cs.getNumberOfRegions());
793
794     one.set(3);
795     cs = new HiddenColumns();
796     cs.hideMarkedBits(one);
797     assertEquals(1, cs.getNumberOfRegions());
798
799     // split
800     one.clear(2);
801     cs = new HiddenColumns();
802     cs.hideMarkedBits(one);
803     assertEquals(2, cs.getNumberOfRegions());
804
805     assertEquals(0, cs.adjustForHiddenColumns(0));
806     assertEquals(2, cs.adjustForHiddenColumns(1));
807     assertEquals(4, cs.adjustForHiddenColumns(2));
808
809     // one again
810     one.clear(1);
811     cs = new HiddenColumns();
812     cs.hideMarkedBits(one);
813
814     assertEquals(1, cs.getNumberOfRegions());
815
816     assertEquals(0, cs.adjustForHiddenColumns(0));
817     assertEquals(1, cs.adjustForHiddenColumns(1));
818     assertEquals(2, cs.adjustForHiddenColumns(2));
819     assertEquals(4, cs.adjustForHiddenColumns(3));
820   }
821
822   @Test(groups = { "Functional" })
823   public void testMarkHiddenRegions()
824   {
825     BitSet toMark, fromMark;
826     long seed = -3241532;
827     Random number = new Random(seed);
828     for (int n = 0; n < 1000; n++)
829     {
830       // create a random bitfield
831       toMark = BitSet
832               .valueOf(new long[]
833       { number.nextLong(), number.nextLong(), number.nextLong() });
834       toMark.set(n * number.nextInt(10), n * (25 + number.nextInt(25)));
835       HiddenColumns hc = new HiddenColumns();
836       hc.hideMarkedBits(toMark);
837
838       // see if we can recover bitfield
839       hc.markHiddenRegions(fromMark = new BitSet());
840       assertEquals(toMark, fromMark);
841     }
842   }
843
844   @Test(groups = { "Functional" })
845   public void testRegionsToString()
846   {
847     HiddenColumns hc = new HiddenColumns();
848
849     String result = hc.regionsToString(",", "--");
850     assertEquals("", result);
851
852     hc.hideColumns(3, 7);
853     hc.hideColumns(10, 10);
854     hc.hideColumns(14, 15);
855
856     result = hc.regionsToString(",", "--");
857     assertEquals("3--7,10--10,14--15", result);
858   }
859
860   @Test(groups = "Functional")
861   public void testGetVisibleStartAndEndIndexTest()
862   {
863     Sequence seq = new Sequence("testSeq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
864     AlignmentI align = new Alignment(new SequenceI[] { seq });
865     HiddenColumns hc = new HiddenColumns();
866
867     int[] startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
868     assertEquals(0, startEnd[0]);
869     assertEquals(25, startEnd[1]);
870
871     hc.hideColumns(0, 0);
872     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
873     assertEquals(1, startEnd[0]);
874     assertEquals(25, startEnd[1]);
875
876     hc.hideColumns(6, 9);
877     hc.hideColumns(11, 12);
878     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
879     assertEquals(1, startEnd[0]);
880     assertEquals(25, startEnd[1]);
881
882     hc.hideColumns(24, 25);
883     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
884     System.out.println(startEnd[0] + " : " + startEnd[1]);
885     assertEquals(1, startEnd[0]);
886     assertEquals(23, startEnd[1]);
887   }
888
889   @Test(groups = "Functional")
890   public void testGetRegionWithEdgeAtRes()
891   {
892     HiddenColumns hc = new HiddenColumns();
893
894     int[] result = hc.getRegionWithEdgeAtRes(5);
895     assertNull(result);
896
897     hc.hideColumns(3, 7);
898     hc.hideColumns(10, 10);
899     hc.hideColumns(14, 15);
900
901     result = hc.getRegionWithEdgeAtRes(2);
902     assertEquals(3, result[0]);
903     assertEquals(7, result[1]);
904
905     result = hc.getRegionWithEdgeAtRes(5);
906     assertEquals(10, result[0]);
907     assertEquals(10, result[1]);
908
909     result = hc.getRegionWithEdgeAtRes(6);
910     assertNull(result);
911
912     result = hc.getRegionWithEdgeAtRes(0);
913     assertNull(result);
914
915     result = hc.getRegionWithEdgeAtRes(7);
916     assertEquals(14, result[0]);
917     assertEquals(15, result[1]);
918
919     result = hc.getRegionWithEdgeAtRes(8);
920     assertEquals(14, result[0]);
921     assertEquals(15, result[1]);
922   }
923
924   @Test(groups = "Functional")
925   public void testPropagateInsertions()
926   {
927     // create an alignment with no gaps - this will be the profile seq and other
928     // JPRED seqs
929     AlignmentGenerator gen = new AlignmentGenerator(false);
930     AlignmentI al = gen.generate(25, 10, 1234, 0, 0);
931
932     // get the profileseq
933     SequenceI profileseq = al.getSequenceAt(0);
934     SequenceI gappedseq = new Sequence(profileseq);
935     gappedseq.insertCharAt(5, al.getGapCharacter());
936     gappedseq.insertCharAt(6, al.getGapCharacter());
937     gappedseq.insertCharAt(7, al.getGapCharacter());
938     gappedseq.insertCharAt(8, al.getGapCharacter());
939
940     // create an alignment view with the gapped sequence
941     SequenceI[] seqs = new SequenceI[1];
942     seqs[0] = gappedseq;
943     AlignmentI newal = new Alignment(seqs);
944     HiddenColumns hidden = new HiddenColumns();
945     hidden.hideColumns(15, 17);
946
947     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
948             false);
949
950     // confirm that original contigs are as expected
951     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 25);
952     int[] region = visible.next();
953     assertEquals("[0, 14]", Arrays.toString(region));
954     region = visible.next();
955     assertEquals("[18, 24]", Arrays.toString(region));
956
957     // propagate insertions
958     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
959             view);
960
961     // confirm that the contigs have changed to account for the gaps
962     visible = result.getVisContigsIterator(0, 25);
963     region = visible.next();
964     assertEquals("[0, 10]", Arrays.toString(region));
965     region = visible.next();
966     assertEquals("[14, 24]", Arrays.toString(region));
967
968     // confirm the alignment has been changed so that the other sequences have
969     // gaps inserted where the columns are hidden
970     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[10]));
971     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[11]));
972     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[12]));
973     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[13]));
974     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[14]));
975
976   }
977
978   @Test(groups = "Functional")
979   public void testPropagateInsertionsOverlap()
980   {
981     // test propagateInsertions where gaps and hiddenColumns overlap
982
983     // create an alignment with no gaps - this will be the profile seq and other
984     // JPRED seqs
985     AlignmentGenerator gen = new AlignmentGenerator(false);
986     AlignmentI al = gen.generate(20, 10, 1234, 0, 0);
987
988     // get the profileseq
989     SequenceI profileseq = al.getSequenceAt(0);
990     SequenceI gappedseq = new Sequence(profileseq);
991     gappedseq.insertCharAt(5, al.getGapCharacter());
992     gappedseq.insertCharAt(6, al.getGapCharacter());
993     gappedseq.insertCharAt(7, al.getGapCharacter());
994     gappedseq.insertCharAt(8, al.getGapCharacter());
995
996     // create an alignment view with the gapped sequence
997     SequenceI[] seqs = new SequenceI[1];
998     seqs[0] = gappedseq;
999     AlignmentI newal = new Alignment(seqs);
1000
1001     // hide columns so that some overlap with the gaps
1002     HiddenColumns hidden = new HiddenColumns();
1003     hidden.hideColumns(7, 10);
1004
1005     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
1006             false);
1007
1008     // confirm that original contigs are as expected
1009     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 20);
1010     int[] region = visible.next();
1011     assertEquals("[0, 6]", Arrays.toString(region));
1012     region = visible.next();
1013     assertEquals("[11, 19]", Arrays.toString(region));
1014     assertFalse(visible.hasNext());
1015
1016     // propagate insertions
1017     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
1018             view);
1019
1020     // confirm that the contigs have changed to account for the gaps
1021     visible = result.getVisContigsIterator(0, 20);
1022     region = visible.next();
1023     assertEquals("[0, 4]", Arrays.toString(region));
1024     region = visible.next();
1025     assertEquals("[7, 19]", Arrays.toString(region));
1026     assertFalse(visible.hasNext());
1027
1028     // confirm the alignment has been changed so that the other sequences have
1029     // gaps inserted where the columns are hidden
1030     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[4]));
1031     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[5]));
1032     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[6]));
1033     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[7]));
1034   }
1035
1036   @Test(groups = "Functional")
1037   public void testHasHiddenColumns()
1038   {
1039     HiddenColumns h = new HiddenColumns();
1040
1041     // new HiddenColumns2 has no hidden cols
1042     assertFalse(h.hasHiddenColumns());
1043
1044     // some columns hidden, returns true
1045     h.hideColumns(5, 10);
1046     assertTrue(h.hasHiddenColumns());
1047
1048     // reveal columns, no hidden cols again
1049     ColumnSelection sel = new ColumnSelection();
1050     h.revealAllHiddenColumns(sel);
1051     assertFalse(h.hasHiddenColumns());
1052   }
1053
1054   @Test(groups = "Functional")
1055   public void testHasManyHiddenColumns()
1056   {
1057     HiddenColumns h = new HiddenColumns();
1058
1059     // new HiddenColumns2 has no hidden cols
1060     assertFalse(h.hasManyHiddenColumns());
1061
1062     // one set of columns hidden, returns false
1063     h.hideColumns(5, 10);
1064     assertFalse(h.hasManyHiddenColumns());
1065
1066     // two sets hidden, returns true
1067     h.hideColumns(15, 17);
1068     assertTrue(h.hasManyHiddenColumns());
1069
1070     // back to one block, asserts false
1071     h.hideColumns(11, 14);
1072     assertFalse(h.hasManyHiddenColumns());
1073   }
1074
1075   @Test(groups = "Functional")
1076   public void testAdjustForHiddenColumns()
1077   {
1078     HiddenColumns h = new HiddenColumns();
1079     // returns input value when there are no hidden columns
1080     assertEquals(10, h.adjustForHiddenColumns(10));
1081
1082     h.hideColumns(20, 30);
1083     assertEquals(10, h.adjustForHiddenColumns(10));
1084     assertEquals(20 + 11, h.adjustForHiddenColumns(20));
1085     assertEquals(35 + 11, h.adjustForHiddenColumns(35));
1086
1087     h.hideColumns(5, 7);
1088     assertEquals(10 + 3, h.adjustForHiddenColumns(10));
1089     assertEquals(20 + 14, h.adjustForHiddenColumns(20));
1090     assertEquals(35 + 14, h.adjustForHiddenColumns(35));
1091
1092     ColumnSelection sel = new ColumnSelection();
1093     h.revealAllHiddenColumns(sel);
1094     h.hideColumns(0, 1);
1095     assertEquals(4, h.adjustForHiddenColumns(2));
1096   }
1097
1098   @Test(groups = "Functional")
1099   public void testGetHiddenBoundaryLeft()
1100   {
1101     HiddenColumns h = new HiddenColumns();
1102
1103     // returns same value if no hidden cols
1104     assertEquals(3, h.getHiddenBoundaryLeft(3));
1105
1106     h.hideColumns(5, 10);
1107     assertEquals(10, h.getHiddenBoundaryLeft(15));
1108     assertEquals(3, h.getHiddenBoundaryLeft(3));
1109     assertEquals(7, h.getHiddenBoundaryLeft(7));
1110
1111     h.hideColumns(15, 20);
1112     assertEquals(10, h.getHiddenBoundaryLeft(15));
1113     assertEquals(20, h.getHiddenBoundaryLeft(21));
1114   }
1115
1116   @Test(groups = "Functional")
1117   public void testGetHiddenBoundaryRight()
1118   {
1119     HiddenColumns h = new HiddenColumns();
1120
1121     // returns same value if no hidden cols
1122     assertEquals(3, h.getHiddenBoundaryRight(3));
1123
1124     h.hideColumns(5, 10);
1125     assertEquals(5, h.getHiddenBoundaryRight(3));
1126     assertEquals(15, h.getHiddenBoundaryRight(15));
1127     assertEquals(7, h.getHiddenBoundaryRight(7));
1128
1129     h.hideColumns(15, 20);
1130     assertEquals(15, h.getHiddenBoundaryRight(7));
1131     assertEquals(15, h.getHiddenBoundaryRight(14));
1132   }
1133
1134   @Test(groups = "Functional")
1135   public void testIterator()
1136   {
1137     HiddenColumns h = new HiddenColumns();
1138     Iterator<int[]> result = h.iterator();
1139     assertFalse(result.hasNext());
1140
1141     h.hideColumns(5, 10);
1142     result = h.iterator();
1143     int[] next = result.next();
1144     assertEquals(5, next[0]);
1145     assertEquals(10, next[1]);
1146     assertFalse(result.hasNext());
1147
1148     h.hideColumns(22, 23);
1149     result = h.iterator();
1150     next = result.next();
1151     assertEquals(5, next[0]);
1152     assertEquals(10, next[1]);
1153     next = result.next();
1154     assertEquals(22, next[0]);
1155     assertEquals(23, next[1]);
1156     assertFalse(result.hasNext());
1157
1158     // test for only one hidden region at start of alignment
1159     ColumnSelection sel = new ColumnSelection();
1160     h.revealAllHiddenColumns(sel);
1161     h.hideColumns(0, 1);
1162     result = h.iterator();
1163     next = result.next();
1164     assertEquals(0, next[0]);
1165     assertEquals(1, next[1]);
1166     assertFalse(result.hasNext());
1167   }
1168
1169   @Test(groups = "Functional")
1170   public void testGetVisibleSequenceStrings()
1171   {
1172     HiddenColumns h = new HiddenColumns();
1173     SequenceI seq1 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1174     SequenceI seq2 = new Sequence("TEST2", "VICYHRNDTGA");
1175     SequenceI[] seqs = new SequenceI[2];
1176     seqs[0] = seq1;
1177     seqs[1] = seq2;
1178     String[] result = h.getVisibleSequenceStrings(5, 10, seqs);
1179     assertEquals(2, result.length);
1180     assertEquals("WKQES", result[0]);
1181     assertEquals("RNDTG", result[1]);
1182
1183     h.hideColumns(6, 8);
1184     result = h.getVisibleSequenceStrings(5, 10, seqs);
1185     assertEquals(2, result.length);
1186     assertEquals("WS", result[0]);
1187     assertEquals("RG", result[1]);
1188
1189     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
1190     ColumnSelection sel = new ColumnSelection();
1191     h.revealAllHiddenColumns(sel);
1192     h.hideColumns(1, 3);
1193     h.hideColumns(6, 11);
1194     assertEquals("-D",
1195             h.getVisibleSequenceStrings(0, 5, new SequenceI[]
1196     { seq })[0]);
1197   }
1198
1199   @Test(groups = "Functional")
1200   public void testHideInsertionsFor()
1201   {
1202     HiddenColumns h = new HiddenColumns();
1203     HiddenColumns h2 = new HiddenColumns();
1204     SequenceI seq1 = new Sequence("TEST1", "GAL---MFW-KQESPVICY--HRNDT");
1205     SequenceI seq2 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1206
1207     h.hideInsertionsFor(seq2);
1208     assertTrue(h.equals(h2));
1209
1210     h.hideInsertionsFor(seq1);
1211     h2.hideColumns(3, 5);
1212     h2.hideColumns(9, 9);
1213     h2.hideColumns(19, 20);
1214     assertTrue(h.equals(h2));
1215   }
1216
1217   @Test(groups = "Functional")
1218   public void testHideMarkedBits()
1219   {
1220     HiddenColumns h = new HiddenColumns();
1221     HiddenColumns h2 = new HiddenColumns();
1222
1223     BitSet tohide = new BitSet(21);
1224     h.hideMarkedBits(tohide);
1225     assertTrue(h.equals(h2));
1226
1227     // NB in hideMarkedBits, the last bit is not set to hidden
1228     tohide.set(3, 6);
1229     tohide.set(9);
1230     tohide.set(19, 21);
1231     h.hideMarkedBits(tohide);
1232
1233     h2.hideColumns(3, 5);
1234     h2.hideColumns(9, 9);
1235     h2.hideColumns(19, 20);
1236     assertTrue(h.equals(h2));
1237   }
1238
1239   @Test(groups = "Functional")
1240   public void testMakeVisibleAnnotation()
1241   {
1242     HiddenColumns h = new HiddenColumns();
1243     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
1244         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1245         new Annotation(5), new Annotation(6), new Annotation(7),
1246         new Annotation(8) };
1247     AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
1248             anns);
1249
1250     // without hidden cols, just truncates
1251     h.makeVisibleAnnotation(3, 5, ann);
1252     assertEquals(3, ann.annotations.length);
1253     assertEquals(2.0f, ann.annotations[0].value);
1254     assertEquals(3.0f, ann.annotations[1].value);
1255     assertNull(ann.annotations[2]);
1256
1257     anns = new Annotation[] { null, null, new Annotation(1),
1258         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1259         new Annotation(5), new Annotation(6), new Annotation(7),
1260         new Annotation(8) };
1261     ann = new AlignmentAnnotation("an", "some an", anns);
1262     h.hideColumns(4, 7);
1263     h.makeVisibleAnnotation(1, 9, ann);
1264     assertEquals(5, ann.annotations.length);
1265     assertNull(ann.annotations[0]);
1266     assertEquals(1.0f, ann.annotations[1].value);
1267     assertEquals(2.0f, ann.annotations[2].value);
1268     assertEquals(5.0f, ann.annotations[3].value);
1269     assertEquals(6.0f, ann.annotations[4].value);
1270
1271     anns = new Annotation[] { null, null, new Annotation(1),
1272         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1273         new Annotation(5), new Annotation(6), new Annotation(7),
1274         new Annotation(8) };
1275     ann = new AlignmentAnnotation("an", "some an", anns);
1276     h.hideColumns(1, 2);
1277     h.makeVisibleAnnotation(1, 9, ann);
1278     assertEquals(3, ann.annotations.length);
1279     assertEquals(2.0f, ann.annotations[0].value);
1280     assertEquals(5.0f, ann.annotations[1].value);
1281     assertEquals(6.0f, ann.annotations[2].value);
1282   }
1283
1284   @Test(groups = "Functional")
1285   public void testSubtractVisibleColumns()
1286   {
1287     HiddenColumns h = new HiddenColumns();
1288     int result = h.subtractVisibleColumns(1, 10);
1289     assertEquals(9, result);
1290
1291     h.hideColumns(7, 9);
1292     result = h.subtractVisibleColumns(4, 10);
1293     assertEquals(3, result);
1294
1295     h.hideColumns(14, 15);
1296     result = h.subtractVisibleColumns(4, 10);
1297     assertEquals(3, result);
1298
1299     result = h.subtractVisibleColumns(10, 17);
1300     assertEquals(2, result);
1301
1302     result = h.subtractVisibleColumns(1, 7);
1303     assertEquals(5, result);
1304
1305     result = h.subtractVisibleColumns(1, 8);
1306     assertEquals(5, result);
1307
1308     result = h.subtractVisibleColumns(3, 15);
1309     assertEquals(10, result);
1310
1311     ColumnSelection sel = new ColumnSelection();
1312     h.revealAllHiddenColumns(sel);
1313     h.hideColumns(0, 30);
1314     result = h.subtractVisibleColumns(31, 0);
1315     assertEquals(-31, result);
1316   }
1317
1318   @Test(groups = "Functional")
1319   public void testBoundedIterator()
1320   {
1321     HiddenColumns h = new HiddenColumns();
1322     Iterator<int[]> it = h.getBoundedIterator(0, 10);
1323
1324     // no hidden columns = nothing to iterate over
1325     assertFalse(it.hasNext());
1326
1327     // [start,end] contains all hidden columns
1328     // all regions are returned
1329     h.hideColumns(3, 10);
1330     h.hideColumns(14, 16);
1331     it = h.getBoundedIterator(0, 20);
1332     assertTrue(it.hasNext());
1333     int[] next = it.next();
1334     assertEquals(3, next[0]);
1335     assertEquals(10, next[1]);
1336     next = it.next();
1337     assertEquals(14, next[0]);
1338     assertEquals(16, next[1]);
1339     assertFalse(it.hasNext());
1340
1341     // [start,end] overlaps a region
1342     // 1 region returned
1343     it = h.getBoundedIterator(5, 7);
1344     assertTrue(it.hasNext());
1345     next = it.next();
1346     assertEquals(3, next[0]);
1347     assertEquals(10, next[1]);
1348     assertFalse(it.hasNext());
1349
1350     // [start,end] fully contains 1 region and start of last
1351     // - 2 regions returned
1352     it = h.getBoundedIterator(3, 15);
1353     assertTrue(it.hasNext());
1354     next = it.next();
1355     assertEquals(3, next[0]);
1356     assertEquals(10, next[1]);
1357     next = it.next();
1358     assertEquals(14, next[0]);
1359     assertEquals(16, next[1]);
1360     assertFalse(it.hasNext());
1361
1362     // [start,end] contains end of first region and whole of last region
1363     // - 2 regions returned
1364     it = h.getBoundedIterator(4, 20);
1365     assertTrue(it.hasNext());
1366     next = it.next();
1367     assertEquals(3, next[0]);
1368     assertEquals(10, next[1]);
1369     next = it.next();
1370     assertEquals(14, next[0]);
1371     assertEquals(16, next[1]);
1372     assertFalse(it.hasNext());
1373   }
1374
1375   @Test(groups = "Functional")
1376   public void testBoundedStartIterator()
1377   {
1378     HiddenColumns h = new HiddenColumns();
1379     Iterator<Integer> it = h.getBoundedStartIterator(0, 10);
1380
1381     // no hidden columns = nothing to iterate over
1382     assertFalse(it.hasNext());
1383
1384     // [start,end] contains all hidden columns
1385     // all regions are returned
1386     h.hideColumns(3, 10);
1387     h.hideColumns(14, 16);
1388     it = h.getBoundedStartIterator(0, 20);
1389     assertTrue(it.hasNext());
1390     int next = it.next();
1391     assertEquals(3, next);
1392     next = it.next();
1393     assertEquals(6, next);
1394     assertFalse(it.hasNext());
1395
1396     // [start,end] does not contain a start of a region
1397     // no regions to iterate over
1398     it = h.getBoundedStartIterator(4, 5);
1399     assertFalse(it.hasNext());
1400
1401     // [start,end] fully contains 1 region and start of last
1402     // - 2 regions returned
1403     it = h.getBoundedStartIterator(3, 7);
1404     assertTrue(it.hasNext());
1405     next = it.next();
1406     assertEquals(3, next);
1407     next = it.next();
1408     assertEquals(6, next);
1409     assertFalse(it.hasNext());
1410
1411     // [start,end] contains whole of last region
1412     // - 1 region returned
1413     it = h.getBoundedStartIterator(4, 20);
1414     assertTrue(it.hasNext());
1415     next = it.next();
1416     assertEquals(6, next);
1417     assertFalse(it.hasNext());
1418   }
1419
1420   @Test(groups = "Functional")
1421   public void testVisibleBlocksVisBoundsIterator()
1422   {
1423     HiddenColumns h = new HiddenColumns();
1424     Iterator<int[]> regions = h.getVisibleBlocksIterator(0, 30, true);
1425
1426     // only 1 visible region spanning 0-30 if nothing is hidden
1427     assertTrue(regions.hasNext());
1428     int[] region = regions.next();
1429     assertEquals(0, region[0]);
1430     assertEquals(30, region[1]);
1431     assertFalse(regions.hasNext());
1432
1433     // hide 1 region in middle
1434     // 2 regions one on either side
1435     // second region boundary accounts for hidden columns
1436     h.hideColumns(10, 15);
1437     regions = h.getVisibleBlocksIterator(0, 30, true);
1438
1439     assertTrue(regions.hasNext());
1440     region = regions.next();
1441     assertEquals(0, region[0]);
1442     assertEquals(9, region[1]);
1443     region = regions.next();
1444     assertEquals(16, region[0]);
1445     assertEquals(36, region[1]);
1446     assertFalse(regions.hasNext());
1447
1448     // single hidden region at left
1449     h = new HiddenColumns();
1450     h.hideColumns(0, 5);
1451     regions = h.getVisibleBlocksIterator(0, 30, true);
1452
1453     assertTrue(regions.hasNext());
1454     region = regions.next();
1455     assertEquals(6, region[0]);
1456     assertEquals(36, region[1]);
1457     assertFalse(regions.hasNext());
1458
1459     // single hidden region at right
1460     h = new HiddenColumns();
1461     h.hideColumns(27, 30);
1462     regions = h.getVisibleBlocksIterator(0, 30, true);
1463
1464     assertTrue(regions.hasNext());
1465     region = regions.next();
1466     assertEquals(0, region[0]);
1467     assertEquals(26, region[1]);
1468     region = regions.next();
1469     assertEquals(31, region[0]);
1470     assertEquals(34, region[1]);
1471     assertFalse(regions.hasNext());
1472
1473     // hidden region at left + hidden region in middle
1474     h = new HiddenColumns();
1475     h.hideColumns(0, 5);
1476     h.hideColumns(23, 25);
1477     regions = h.getVisibleBlocksIterator(0, 30, true);
1478
1479     assertTrue(regions.hasNext());
1480     region = regions.next();
1481     assertEquals(6, region[0]);
1482     assertEquals(22, region[1]);
1483     region = regions.next();
1484     assertEquals(26, region[0]);
1485     assertEquals(39, region[1]);
1486     assertFalse(regions.hasNext());
1487
1488     // hidden region at right + hidden region in middle
1489     h = new HiddenColumns();
1490     h.hideColumns(27, 30);
1491     h.hideColumns(11, 14);
1492     regions = h.getVisibleBlocksIterator(0, 30, true);
1493
1494     assertTrue(regions.hasNext());
1495     region = regions.next();
1496     assertEquals(0, region[0]);
1497     assertEquals(10, region[1]);
1498     region = regions.next();
1499     assertEquals(15, region[0]);
1500     assertEquals(26, region[1]);
1501     region = regions.next();
1502     assertEquals(31, region[0]);
1503     assertEquals(38, region[1]);
1504     assertFalse(regions.hasNext());
1505
1506     // hidden region at left and right
1507     h = new HiddenColumns();
1508     h.hideColumns(27, 35);
1509     h.hideColumns(0, 4);
1510     regions = h.getVisibleBlocksIterator(0, 30, true);
1511
1512     assertTrue(regions.hasNext());
1513     region = regions.next();
1514     assertEquals(5, region[0]);
1515     assertEquals(26, region[1]);
1516     region = regions.next();
1517     assertEquals(36, region[0]);
1518     assertEquals(44, region[1]);
1519     assertFalse(regions.hasNext());
1520
1521     // multiple hidden regions
1522     h = new HiddenColumns();
1523     h.hideColumns(1, 1);
1524     h.hideColumns(3, 5);
1525     h.hideColumns(9, 11);
1526     h.hideColumns(22, 26);
1527
1528     regions = h.getVisibleBlocksIterator(0, 30, true);
1529
1530     assertTrue(regions.hasNext());
1531     region = regions.next();
1532     assertEquals(0, region[0]);
1533     assertEquals(0, region[1]);
1534     region = regions.next();
1535     assertEquals(2, region[0]);
1536     assertEquals(2, region[1]);
1537     region = regions.next();
1538     assertEquals(6, region[0]);
1539     assertEquals(8, region[1]);
1540     region = regions.next();
1541     assertEquals(12, region[0]);
1542     assertEquals(21, region[1]);
1543     region = regions.next();
1544     assertEquals(27, region[0]);
1545     assertEquals(42, region[1]);
1546     assertFalse(regions.hasNext());
1547   }
1548 }