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