e4aa8e2ff78aac3e0f132a84cc77111a700faec1
[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     cs.hideColumns(2, 4);
460     cs.hideColumns(6, 7);
461     assertTrue(cs.isVisible(0));
462     assertTrue(cs.isVisible(-99));
463     assertTrue(cs.isVisible(1));
464     assertFalse(cs.isVisible(2));
465     assertFalse(cs.isVisible(3));
466     assertFalse(cs.isVisible(4));
467     assertTrue(cs.isVisible(5));
468     assertFalse(cs.isVisible(6));
469     assertFalse(cs.isVisible(7));
470     assertTrue(cs.isVisible(8));
471   }
472
473   /**
474    * Test for the case when a hidden range encloses more one already hidden
475    * range
476    */
477   @Test(groups = { "Functional" })
478   public void testHideColumns_subsumingHidden()
479   {
480     /*
481      * JAL-2370 bug scenario:
482      * two hidden ranges subsumed by a third
483      */
484     HiddenColumns cs = new HiddenColumns();
485     cs.hideColumns(49, 59);
486     cs.hideColumns(69, 79);
487     Iterator<int[]> regions = cs.iterator();
488     assertEquals(2, cs.getNumberOfRegions());
489     assertEquals("[49, 59]", Arrays.toString(regions.next()));
490     assertEquals("[69, 79]", Arrays.toString(regions.next()));
491     assertEquals(22, cs.getSize());
492
493     cs.hideColumns(48, 80);
494     regions = cs.iterator();
495     assertEquals(1, cs.getNumberOfRegions());
496     assertEquals("[48, 80]", Arrays.toString(regions.next()));
497     assertEquals(33, cs.getSize());
498
499     /*
500      * another...joining hidden ranges
501      */
502     cs = new HiddenColumns();
503     cs.hideColumns(10, 20);
504     cs.hideColumns(30, 40);
505     cs.hideColumns(50, 60);
506     // hiding 21-49 should merge to one range
507     cs.hideColumns(21, 49);
508     regions = cs.iterator();
509     assertEquals(1, cs.getNumberOfRegions());
510     assertEquals("[10, 60]", Arrays.toString(regions.next()));
511     assertEquals(51, cs.getSize());
512
513     /*
514      * another...left overlap, subsumption, right overlap,
515      * no overlap of existing hidden ranges
516      */
517     cs = new HiddenColumns();
518     cs.hideColumns(10, 20);
519     cs.hideColumns(10, 20);
520     cs.hideColumns(30, 35);
521     cs.hideColumns(40, 50);
522     cs.hideColumns(60, 70);
523
524     cs.hideColumns(15, 45);
525     regions = cs.iterator();
526     assertEquals(2, cs.getNumberOfRegions());
527     assertEquals("[10, 50]", Arrays.toString(regions.next()));
528     assertEquals("[60, 70]", Arrays.toString(regions.next()));
529     assertEquals(52, cs.getSize());
530   }
531
532   @Test(groups = { "Functional" })
533   public void testHideColumns_BitSet()
534   {
535     HiddenColumns cs;
536
537     BitSet one = new BitSet();
538
539     // one hidden range
540     one.set(1);
541     cs = new HiddenColumns();
542     cs.hideColumns(one);
543     assertEquals(1, cs.getNumberOfRegions());
544     assertEquals(1, cs.getSize());
545
546     one.set(2);
547     cs = new HiddenColumns();
548     cs.hideColumns(one);
549     assertEquals(1, cs.getNumberOfRegions());
550     assertEquals(2, cs.getSize());
551
552     one.set(3);
553     cs = new HiddenColumns();
554     cs.hideColumns(one);
555     assertEquals(1, cs.getNumberOfRegions());
556     assertEquals(3, cs.getSize());
557
558     // split
559     one.clear(2);
560     cs = new HiddenColumns();
561     cs.hideColumns(one);
562     assertEquals(2, cs.getNumberOfRegions());
563     assertEquals(2, cs.getSize());
564
565     assertEquals(0, cs.visibleToAbsoluteColumn(0));
566     assertEquals(2, cs.visibleToAbsoluteColumn(1));
567     assertEquals(4, cs.visibleToAbsoluteColumn(2));
568
569     // one again
570     one.clear(1);
571     cs = new HiddenColumns();
572     cs.hideColumns(one);
573     assertEquals(1, cs.getSize());
574
575     assertEquals(1, cs.getNumberOfRegions());
576
577     assertEquals(0, cs.visibleToAbsoluteColumn(0));
578     assertEquals(1, cs.visibleToAbsoluteColumn(1));
579     assertEquals(2, cs.visibleToAbsoluteColumn(2));
580     assertEquals(4, cs.visibleToAbsoluteColumn(3));
581   }
582
583   @Test(groups = { "Functional" })
584   public void testRegionsToString()
585   {
586     HiddenColumns hc = new HiddenColumns();
587
588     String result = hc.regionsToString(",", "--");
589     assertEquals("", result);
590
591     hc.hideColumns(3, 7);
592     hc.hideColumns(10, 10);
593     hc.hideColumns(14, 15);
594
595     result = hc.regionsToString(",", "--");
596     assertEquals("3--7,10--10,14--15", result);
597   }
598
599   @Test(groups = "Functional")
600   public void testGetVisibleStartAndEndIndex()
601   {
602     Sequence seq = new Sequence("testSeq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
603     AlignmentI align = new Alignment(new SequenceI[] { seq });
604     HiddenColumns hc = new HiddenColumns();
605
606     int[] startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
607     assertEquals(0, startEnd[0]);
608     assertEquals(25, startEnd[1]);
609
610     hc.hideColumns(0, 0);
611     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
612     assertEquals(1, startEnd[0]);
613     assertEquals(25, startEnd[1]);
614
615     hc.hideColumns(6, 9);
616     hc.hideColumns(11, 12);
617     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
618     assertEquals(1, startEnd[0]);
619     assertEquals(25, startEnd[1]);
620
621     hc.hideColumns(24, 25);
622     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
623     System.out.println(startEnd[0] + " : " + startEnd[1]);
624     assertEquals(1, startEnd[0]);
625     assertEquals(23, startEnd[1]);
626
627     // force lowest range to start of alignment
628     hc = new HiddenColumns();
629     hc.hideColumns(3, 4);
630     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
631     assertEquals(0, startEnd[0]);
632     assertEquals(25, startEnd[1]);
633   }
634
635   @Test(groups = "Functional")
636   public void testGetRegionWithEdgeAtRes()
637   {
638     HiddenColumns hc = new HiddenColumns();
639
640     int[] result = hc.getRegionWithEdgeAtRes(5);
641     assertNull(result);
642
643     hc.hideColumns(3, 7);
644     hc.hideColumns(10, 10);
645     hc.hideColumns(14, 15);
646
647     result = hc.getRegionWithEdgeAtRes(2);
648     assertEquals(3, result[0]);
649     assertEquals(7, result[1]);
650
651     result = hc.getRegionWithEdgeAtRes(4);
652     assertEquals(10, result[0]);
653     assertEquals(10, result[1]);
654
655     result = hc.getRegionWithEdgeAtRes(5);
656     assertEquals(10, result[0]);
657     assertEquals(10, result[1]);
658
659     result = hc.getRegionWithEdgeAtRes(6);
660     assertNull(result);
661
662     result = hc.getRegionWithEdgeAtRes(0);
663     assertNull(result);
664
665     result = hc.getRegionWithEdgeAtRes(7);
666     assertEquals(14, result[0]);
667     assertEquals(15, result[1]);
668
669     result = hc.getRegionWithEdgeAtRes(8);
670     assertEquals(14, result[0]);
671     assertEquals(15, result[1]);
672
673     result = hc.getRegionWithEdgeAtRes(16);
674     assertNull(result);
675   }
676
677   @Test(groups = "Functional")
678   public void testHasHiddenColumns()
679   {
680     HiddenColumns h = new HiddenColumns();
681
682     // new HiddenColumns2 has no hidden cols
683     assertFalse(h.hasHiddenColumns());
684
685     // some columns hidden, returns true
686     h.hideColumns(5, 10);
687     assertTrue(h.hasHiddenColumns());
688
689     // reveal columns, no hidden cols again
690     ColumnSelection sel = new ColumnSelection();
691     h.revealAllHiddenColumns(sel);
692     assertFalse(h.hasHiddenColumns());
693   }
694
695   @Test(groups = "Functional")
696   public void testHasManyHiddenColumns()
697   {
698     HiddenColumns h = new HiddenColumns();
699
700     // h has no hidden cols
701     assertFalse(h.hasMultiHiddenColumnRegions());
702
703     // one set of columns hidden, returns false
704     h.hideColumns(5, 10);
705     assertFalse(h.hasMultiHiddenColumnRegions());
706
707     // two sets hidden, returns true
708     h.hideColumns(15, 17);
709     assertTrue(h.hasMultiHiddenColumnRegions());
710
711     // back to one block, asserts false
712     h.hideColumns(11, 14);
713     assertFalse(h.hasMultiHiddenColumnRegions());
714   }
715
716   @Test(groups = "Functional")
717   public void testAdjustForHiddenColumns()
718   {
719     HiddenColumns h = new HiddenColumns();
720     // returns input value when there are no hidden columns
721     assertEquals(10, h.visibleToAbsoluteColumn(10));
722
723     h.hideColumns(20, 30);
724     assertEquals(10, h.visibleToAbsoluteColumn(10));
725     assertEquals(20 + 11, h.visibleToAbsoluteColumn(20));
726     assertEquals(35 + 11, h.visibleToAbsoluteColumn(35));
727
728     h.hideColumns(5, 7);
729     assertEquals(10 + 3, h.visibleToAbsoluteColumn(10));
730     assertEquals(20 + 14, h.visibleToAbsoluteColumn(20));
731     assertEquals(35 + 14, h.visibleToAbsoluteColumn(35));
732
733     ColumnSelection sel = new ColumnSelection();
734     h.revealAllHiddenColumns(sel);
735     h.hideColumns(0, 1);
736     assertEquals(4, h.visibleToAbsoluteColumn(2));
737   }
738
739   @Test(groups = "Functional")
740   public void testGetHiddenBoundaryLeft()
741   {
742     HiddenColumns h = new HiddenColumns();
743
744     // returns same value if no hidden cols
745     assertEquals(3, h.getNextHiddenBoundary(true, 3));
746
747     h.hideColumns(5, 10);
748     assertEquals(10, h.getNextHiddenBoundary(true, 15));
749     assertEquals(3, h.getNextHiddenBoundary(true, 3));
750     assertEquals(7, h.getNextHiddenBoundary(true, 7));
751
752     h.hideColumns(15, 20);
753     assertEquals(10, h.getNextHiddenBoundary(true, 15));
754     assertEquals(20, h.getNextHiddenBoundary(true, 21));
755   }
756
757   @Test(groups = "Functional")
758   public void testGetNextHiddenBoundary()
759   {
760     HiddenColumns h = new HiddenColumns();
761
762     // returns same value if no hidden cols
763     assertEquals(3, h.getNextHiddenBoundary(false, 3));
764
765     h.hideColumns(5, 10);
766     assertEquals(5, h.getNextHiddenBoundary(false, 3));
767     assertEquals(15, h.getNextHiddenBoundary(false, 15));
768     assertEquals(7, h.getNextHiddenBoundary(false, 7));
769
770     h.hideColumns(15, 20);
771     assertEquals(15, h.getNextHiddenBoundary(false, 7));
772     assertEquals(15, h.getNextHiddenBoundary(false, 14));
773
774     // returns same value if there is no next hidden column
775     assertEquals(22, h.getNextHiddenBoundary(false, 22));
776   }
777
778   @Test(groups = "Functional")
779   public void testIterator()
780   {
781     HiddenColumns h = new HiddenColumns();
782     Iterator<int[]> result = h.iterator();
783     assertFalse(result.hasNext());
784
785     h.hideColumns(5, 10);
786     result = h.iterator();
787     int[] next = result.next();
788     assertEquals(5, next[0]);
789     assertEquals(10, next[1]);
790     assertFalse(result.hasNext());
791
792     h.hideColumns(22, 23);
793     result = h.iterator();
794     next = result.next();
795     assertEquals(5, next[0]);
796     assertEquals(10, next[1]);
797     next = result.next();
798     assertEquals(22, next[0]);
799     assertEquals(23, next[1]);
800     assertFalse(result.hasNext());
801
802     // test for only one hidden region at start of alignment
803     ColumnSelection sel = new ColumnSelection();
804     h.revealAllHiddenColumns(sel);
805     h.hideColumns(0, 1);
806     result = h.iterator();
807     next = result.next();
808     assertEquals(0, next[0]);
809     assertEquals(1, next[1]);
810     assertFalse(result.hasNext());
811   }
812
813   /* @Test(groups = "Functional")
814   public void testGetVisibleSequenceStrings()
815   {
816     HiddenColumns h = new HiddenColumns();
817     SequenceI seq1 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
818     SequenceI seq2 = new Sequence("TEST2", "VICYHRNDTGA");
819     SequenceI[] seqs = new SequenceI[2];
820     seqs[0] = seq1;
821     seqs[1] = seq2;
822     String[] result = h.getVisibleSequenceStrings(5, 10, seqs);
823     assertEquals(2, result.length);
824     assertEquals("WKQES", result[0]);
825     assertEquals("RNDTG", result[1]);
826   
827     h.hideColumns(6, 8);
828     result = h.getVisibleSequenceStrings(5, 10, seqs);
829     assertEquals(2, result.length);
830     assertEquals("WS", result[0]);
831     assertEquals("RG", result[1]);
832   
833     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
834     ColumnSelection sel = new ColumnSelection();
835     h.revealAllHiddenColumns(sel);
836     h.hideColumns(1, 3);
837     h.hideColumns(6, 11);
838     assertEquals("-D",
839             h.getVisibleSequenceStrings(0, 5, new SequenceI[]
840     { seq })[0]);
841   }*/
842
843   @Test(groups = "Functional")
844   public void testHideInsertionsFor()
845   {
846     HiddenColumns h = new HiddenColumns();
847     HiddenColumns h2 = new HiddenColumns();
848     SequenceI seq1 = new Sequence("TEST1", "GAL---MFW-KQESPVICY--HRNDT");
849     SequenceI seq2 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
850
851     h.hideList(seq2.getInsertions());
852     assertTrue(h.equals(h2));
853     assertEquals(0, h.getSize());
854
855     h.hideList(seq1.getInsertions());
856     h2.hideColumns(3, 5);
857     h2.hideColumns(9, 9);
858     h2.hideColumns(19, 20);
859     assertTrue(h.equals(h2));
860     assertEquals(6, h.getSize());
861   }
862
863   @Test(groups = "Functional")
864   public void testHideColumns_BitSet_range()
865   {
866     HiddenColumns h = new HiddenColumns();
867     HiddenColumns h2 = new HiddenColumns();
868
869     BitSet tohide = new BitSet(21);
870     h.hideColumns(tohide);
871     assertTrue(h.equals(h2));
872
873     // when setting bitset, first param is inclusive, second exclusive
874     tohide.set(3, 6);
875     tohide.set(9);
876     tohide.set(15, 21);
877     h.hideColumns(tohide, 5, 23);
878
879     h2.hideColumns(5, 5);
880     h2.hideColumns(9, 9);
881     h2.hideColumns(15, 20);
882     assertTrue(h.equals(h2));
883     assertEquals(h.getSize(), h2.getSize());
884
885     tohide.clear();
886     tohide.set(41);
887     h.hideColumns(tohide, 23, 30);
888     assertTrue(h.equals(h2));
889     assertEquals(h.getSize(), h2.getSize());
890
891     tohide.set(41);
892     h.hideColumns(tohide, 30, 45);
893     h2.hideColumns(41, 41);
894     assertTrue(h.equals(h2));
895     assertEquals(h.getSize(), h2.getSize());
896
897     tohide.clear();
898     tohide.set(25, 28);
899     h.hideColumns(tohide, 17, 50);
900     h2 = new HiddenColumns();
901     h2.hideColumns(5, 5);
902     h2.hideColumns(9, 9);
903     h2.hideColumns(15, 16);
904     h2.hideColumns(25, 27);
905     assertTrue(h.equals(h2));
906     assertEquals(h.getSize(), h2.getSize());
907
908     HiddenColumns hc = new HiddenColumns();
909     hc.hideColumns(3, 5);
910     hc.hideColumns(15, 20);
911     hc.hideColumns(45, 60);
912
913     tohide = new BitSet();
914
915     // all unhidden if tohide is empty and range covers hidden
916     hc.hideColumns(tohide, 1, 70);
917     assertTrue(!hc.hasHiddenColumns());
918     assertEquals(0, hc.getSize());
919
920     hc.hideColumns(3, 5);
921     hc.hideColumns(15, 20);
922     hc.hideColumns(45, 60);
923     assertEquals(25, hc.getSize());
924
925     // but not if range does not cover hidden
926     hc.hideColumns(tohide, 23, 40);
927     assertTrue(hc.hasHiddenColumns());
928     assertEquals(25, hc.getSize());
929
930     // and partial unhide if range partially covers
931     hc.hideColumns(tohide, 1, 17);
932     Iterator<int[]> it = hc.iterator();
933     assertTrue(it.hasNext());
934     int[] region = it.next();
935
936     assertEquals(18, region[0]);
937     assertEquals(20, region[1]);
938
939     assertTrue(it.hasNext());
940     region = it.next();
941
942     assertEquals(45, region[0]);
943     assertEquals(60, region[1]);
944
945     assertFalse(it.hasNext());
946     assertEquals(19, hc.getSize());
947   }
948
949   @Test(groups = "Functional")
950   public void testOffsetByVisibleColumns()
951   {
952     HiddenColumns h = new HiddenColumns();
953     int result = h.offsetByVisibleColumns(-1, 10);
954     assertEquals(9, result);
955
956     h.hideColumns(7, 9);
957     result = h.offsetByVisibleColumns(-4, 10);
958     assertEquals(3, result);
959
960     h.hideColumns(14, 15);
961     result = h.offsetByVisibleColumns(-4, 10);
962     assertEquals(3, result);
963
964     result = h.offsetByVisibleColumns(-10, 17);
965     assertEquals(2, result);
966
967     result = h.offsetByVisibleColumns(-1, 7);
968     assertEquals(5, result);
969
970     result = h.offsetByVisibleColumns(-1, 8);
971     assertEquals(5, result);
972
973     result = h.offsetByVisibleColumns(-3, 15);
974     assertEquals(10, result);
975
976     ColumnSelection sel = new ColumnSelection();
977     h.revealAllHiddenColumns(sel);
978     h.hideColumns(0, 30);
979     result = h.offsetByVisibleColumns(-31, 0);
980     assertEquals(-31, result);
981
982     HiddenColumns cs = new HiddenColumns();
983
984     // test that without hidden columns, offsetByVisibleColumns returns
985     // position n to left of provided position
986     long pos = cs.offsetByVisibleColumns(-3, 10);
987     assertEquals(7, pos);
988
989     // 0 returns same position
990     pos = cs.offsetByVisibleColumns(0, 10);
991     assertEquals(10, pos);
992
993     // overflow to left returns negative number
994     pos = cs.offsetByVisibleColumns(-3, 0);
995     assertEquals(-3, pos);
996
997     // test that with hidden columns to left of result column
998     // behaviour is the same as above
999     cs.hideColumns(1, 3);
1000
1001     // position n to left of provided position
1002     pos = cs.offsetByVisibleColumns(-3, 10);
1003     assertEquals(7, pos);
1004
1005     // 0 returns same position
1006     pos = cs.offsetByVisibleColumns(0, 10);
1007     assertEquals(10, pos);
1008
1009     // test with one set of hidden columns between start and required position
1010     cs.hideColumns(12, 15);
1011     pos = cs.offsetByVisibleColumns(-8, 17);
1012     assertEquals(5, pos);
1013
1014     // test with two sets of hidden columns between start and required position
1015     cs.hideColumns(20, 21);
1016     pos = cs.offsetByVisibleColumns(-8, 23);
1017     assertEquals(9, pos);
1018
1019     // repeat last 2 tests with no hidden columns to left of required position
1020     ColumnSelection colsel = new ColumnSelection();
1021     cs.revealAllHiddenColumns(colsel);
1022
1023     // test with one set of hidden columns between start and required position
1024     cs.hideColumns(12, 15);
1025     pos = cs.offsetByVisibleColumns(-8, 17);
1026     assertEquals(5, pos);
1027
1028     // test with two sets of hidden columns between start and required position
1029     cs.hideColumns(20, 21);
1030     pos = cs.offsetByVisibleColumns(-8, 23);
1031     assertEquals(9, pos);
1032
1033     // test with right (positive) offsets
1034
1035     // test that without hidden columns, offsetByVisibleColumns returns
1036     // position n to right of provided position
1037     pos = cs.offsetByVisibleColumns(3, 7);
1038     assertEquals(10, pos);
1039
1040     // test that with hidden columns to left of result column
1041     // behaviour is the same as above
1042     cs.hideColumns(1, 3);
1043
1044     // test with one set of hidden columns between start and required position
1045     cs.hideColumns(12, 15);
1046     pos = cs.offsetByVisibleColumns(8, 5);
1047     assertEquals(17, pos);
1048
1049     // test with two sets of hidden columns between start and required position
1050     cs.hideColumns(20, 21);
1051     pos = cs.offsetByVisibleColumns(8, 9);
1052     assertEquals(23, pos);
1053
1054     // repeat last 2 tests with no hidden columns to left of required position
1055     colsel = new ColumnSelection();
1056     cs.revealAllHiddenColumns(colsel);
1057
1058     // test with one set of hidden columns between start and required position
1059     cs.hideColumns(12, 15);
1060     pos = cs.offsetByVisibleColumns(8, 5);
1061     assertEquals(17, pos);
1062
1063     // test with two sets of hidden columns between start and required position
1064     cs.hideColumns(20, 21);
1065     pos = cs.offsetByVisibleColumns(8, 9);
1066     assertEquals(23, pos);
1067   }
1068
1069   @Test(groups = "Functional")
1070   public void testBoundedIterator()
1071   {
1072     HiddenColumns h = new HiddenColumns();
1073     Iterator<int[]> it = h.getBoundedIterator(0, 10);
1074
1075     // no hidden columns = nothing to iterate over
1076     assertFalse(it.hasNext());
1077
1078     // [start,end] contains all hidden columns
1079     // all regions are returned
1080     h.hideColumns(3, 10);
1081     h.hideColumns(14, 16);
1082     it = h.getBoundedIterator(0, 20);
1083     assertTrue(it.hasNext());
1084     int[] next = it.next();
1085     assertEquals(3, next[0]);
1086     assertEquals(10, next[1]);
1087     next = it.next();
1088     assertEquals(14, next[0]);
1089     assertEquals(16, next[1]);
1090     assertFalse(it.hasNext());
1091
1092     // [start,end] overlaps a region
1093     // 1 region returned
1094     it = h.getBoundedIterator(5, 7);
1095     assertTrue(it.hasNext());
1096     next = it.next();
1097     assertEquals(3, next[0]);
1098     assertEquals(10, next[1]);
1099     assertFalse(it.hasNext());
1100
1101     // [start,end] fully contains 1 region and start of last
1102     // - 2 regions returned
1103     it = h.getBoundedIterator(3, 15);
1104     assertTrue(it.hasNext());
1105     next = it.next();
1106     assertEquals(3, next[0]);
1107     assertEquals(10, next[1]);
1108     next = it.next();
1109     assertEquals(14, next[0]);
1110     assertEquals(16, next[1]);
1111     assertFalse(it.hasNext());
1112
1113     // [start,end] contains end of first region and whole of last region
1114     // - 2 regions returned
1115     it = h.getBoundedIterator(4, 20);
1116     assertTrue(it.hasNext());
1117     next = it.next();
1118     assertEquals(3, next[0]);
1119     assertEquals(10, next[1]);
1120     next = it.next();
1121     assertEquals(14, next[0]);
1122     assertEquals(16, next[1]);
1123     assertFalse(it.hasNext());
1124   }
1125
1126   @Test(groups = "Functional")
1127   public void testBoundedStartIterator()
1128   {
1129     HiddenColumns h = new HiddenColumns();
1130     Iterator<Integer> it = h.getBoundedStartIterator(0, 10);
1131
1132     // no hidden columns = nothing to iterate over
1133     assertFalse(it.hasNext());
1134
1135     // [start,end] contains all hidden columns
1136     // all regions are returned
1137     h.hideColumns(3, 10);
1138     h.hideColumns(14, 16);
1139     it = h.getBoundedStartIterator(0, 20);
1140     assertTrue(it.hasNext());
1141     int next = it.next();
1142     assertEquals(3, next);
1143     next = it.next();
1144     assertEquals(6, next);
1145     assertFalse(it.hasNext());
1146
1147     // [start,end] does not contain a start of a region
1148     // no regions to iterate over
1149     it = h.getBoundedStartIterator(4, 5);
1150     assertFalse(it.hasNext());
1151
1152     // [start,end] fully contains 1 region and start of last
1153     // - 2 regions returned
1154     it = h.getBoundedStartIterator(3, 7);
1155     assertTrue(it.hasNext());
1156     next = it.next();
1157     assertEquals(3, next);
1158     next = it.next();
1159     assertEquals(6, next);
1160     assertFalse(it.hasNext());
1161
1162     // [start,end] contains whole of last region
1163     // - 1 region returned
1164     it = h.getBoundedStartIterator(4, 20);
1165     assertTrue(it.hasNext());
1166     next = it.next();
1167     assertEquals(6, next);
1168     assertFalse(it.hasNext());
1169   }
1170
1171   @Test(groups = "Functional")
1172   public void testVisibleBlocksVisBoundsIterator()
1173   {
1174     HiddenColumns h = new HiddenColumns();
1175     Iterator<int[]> regions = h.getVisContigsIterator(0, 31, true);
1176
1177     // only 1 visible region spanning 0-30 if nothing is hidden
1178     assertTrue(regions.hasNext());
1179     int[] region = regions.next();
1180     assertEquals(0, region[0]);
1181     assertEquals(30, region[1]);
1182     assertFalse(regions.hasNext());
1183
1184     // hide 1 region in middle
1185     // 2 regions one on either side
1186     // second region boundary accounts for hidden columns
1187     h.hideColumns(10, 15);
1188     regions = h.getVisContigsIterator(0, 31, true);
1189
1190     assertTrue(regions.hasNext());
1191     region = regions.next();
1192     assertEquals(0, region[0]);
1193     assertEquals(9, region[1]);
1194     region = regions.next();
1195     assertEquals(16, region[0]);
1196     assertEquals(36, region[1]);
1197     assertFalse(regions.hasNext());
1198
1199     // single hidden region at left
1200     h = new HiddenColumns();
1201     h.hideColumns(0, 5);
1202     regions = h.getVisContigsIterator(0, 31, true);
1203
1204     assertTrue(regions.hasNext());
1205     region = regions.next();
1206     assertEquals(6, region[0]);
1207     assertEquals(36, region[1]);
1208     assertFalse(regions.hasNext());
1209
1210     // single hidden region at right
1211     h = new HiddenColumns();
1212     h.hideColumns(27, 30);
1213     regions = h.getVisContigsIterator(0, 31, true);
1214
1215     assertTrue(regions.hasNext());
1216     region = regions.next();
1217     assertEquals(0, region[0]);
1218     assertEquals(26, region[1]);
1219     region = regions.next();
1220     assertEquals(31, region[0]);
1221     assertEquals(34, region[1]);
1222     assertFalse(regions.hasNext());
1223
1224     // hidden region at left + hidden region in middle
1225     h = new HiddenColumns();
1226     h.hideColumns(0, 5);
1227     h.hideColumns(23, 25);
1228     regions = h.getVisContigsIterator(0, 31, true);
1229
1230     assertTrue(regions.hasNext());
1231     region = regions.next();
1232     assertEquals(6, region[0]);
1233     assertEquals(22, region[1]);
1234     region = regions.next();
1235     assertEquals(26, region[0]);
1236     assertEquals(39, region[1]);
1237     assertFalse(regions.hasNext());
1238
1239     // hidden region at right + hidden region in middle
1240     h = new HiddenColumns();
1241     h.hideColumns(27, 30);
1242     h.hideColumns(11, 14);
1243     regions = h.getVisContigsIterator(0, 31, true);
1244
1245     assertTrue(regions.hasNext());
1246     region = regions.next();
1247     assertEquals(0, region[0]);
1248     assertEquals(10, region[1]);
1249     region = regions.next();
1250     assertEquals(15, region[0]);
1251     assertEquals(26, region[1]);
1252     region = regions.next();
1253     assertEquals(31, region[0]);
1254     assertEquals(38, region[1]);
1255     assertFalse(regions.hasNext());
1256
1257     // hidden region at left and right
1258     h = new HiddenColumns();
1259     h.hideColumns(27, 35);
1260     h.hideColumns(0, 4);
1261     regions = h.getVisContigsIterator(0, 31, true);
1262
1263     assertTrue(regions.hasNext());
1264     region = regions.next();
1265     assertEquals(5, region[0]);
1266     assertEquals(26, region[1]);
1267     region = regions.next();
1268     assertEquals(36, region[0]);
1269     assertEquals(44, region[1]);
1270     assertFalse(regions.hasNext());
1271
1272     // multiple hidden regions
1273     h = new HiddenColumns();
1274     h.hideColumns(1, 1);
1275     h.hideColumns(3, 5);
1276     h.hideColumns(9, 11);
1277     h.hideColumns(22, 26);
1278
1279     regions = h.getVisContigsIterator(0, 31, true);
1280
1281     assertTrue(regions.hasNext());
1282     region = regions.next();
1283     assertEquals(0, region[0]);
1284     assertEquals(0, region[1]);
1285     region = regions.next();
1286     assertEquals(2, region[0]);
1287     assertEquals(2, region[1]);
1288     region = regions.next();
1289     assertEquals(6, region[0]);
1290     assertEquals(8, region[1]);
1291     region = regions.next();
1292     assertEquals(12, region[0]);
1293     assertEquals(21, region[1]);
1294     region = regions.next();
1295     assertEquals(27, region[0]);
1296     assertEquals(42, region[1]);
1297     assertFalse(regions.hasNext());
1298   }
1299
1300   /*
1301    * the VisibleColsIterator is tested elsewhere, this just tests that 
1302    * it can be retrieved from HiddenColumns
1303    */
1304   @Test(groups = "Functional")
1305   public void testGetVisibleColsIterator()
1306   {
1307     HiddenColumns h = new HiddenColumns();
1308     Iterator<Integer> it = h.getVisibleColsIterator(0, 10);
1309
1310     assertTrue(it instanceof VisibleColsIterator);
1311   }
1312
1313   @Test(groups = "Functional")
1314   public void testHashCode()
1315   {
1316     HiddenColumns h = new HiddenColumns();
1317     h.hideColumns(0, 25);
1318
1319     int result = h.hashCode();
1320     assertTrue(result > 0);
1321
1322     h.hideColumns(30, 50);
1323     assertTrue(h.hashCode() > 0);
1324     assertTrue(result != h.hashCode());
1325   }
1326 }