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