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