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