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