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