JAL-2759 Rename hideInsertionsFor to hideList, after review
[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 import jalview.util.Comparison;
30
31 import java.util.Arrays;
32 import java.util.BitSet;
33 import java.util.Iterator;
34 import java.util.Random;
35
36 import org.testng.annotations.Test;
37
38 public class HiddenColumnsTest
39 {
40   /**
41    * Test the method which counts the number of hidden columns
42    */
43   @Test(groups = { "Functional" })
44   public void testGetSize()
45   {
46     HiddenColumns hidden = new HiddenColumns();
47     assertEquals(0, hidden.getSize());
48
49     hidden.hideColumns(3, 5);
50     assertEquals(3, hidden.getSize());
51
52     hidden.hideColumns(8, 8);
53     assertEquals(4, hidden.getSize());
54
55     hidden.hideColumns(9, 14);
56     assertEquals(10, hidden.getSize());
57
58     ColumnSelection cs = new ColumnSelection();
59     hidden.revealAllHiddenColumns(cs);
60     assertEquals(0, hidden.getSize());
61   }
62
63   /**
64    * Test the method that finds the visible column position of an alignment
65    * column, allowing for hidden columns.
66    */
67   @Test(groups = { "Functional" })
68   public void testFindColumnPosition()
69   {
70     HiddenColumns cs = new HiddenColumns();
71     assertEquals(5, cs.absoluteToVisibleColumn(5));
72
73     // hiding column 6 makes no difference
74     cs.hideColumns(6, 6);
75     assertEquals(5, cs.absoluteToVisibleColumn(5));
76
77     // hiding column 4 moves column 5 to column 4
78     cs.hideColumns(4, 4);
79     assertEquals(4, cs.absoluteToVisibleColumn(5));
80
81     // hiding column 4 moves column 4 to position 3
82     assertEquals(3, cs.absoluteToVisibleColumn(4));
83
84     // hiding columns 1 and 2 moves column 5 to column 2
85     cs.hideColumns(1, 2);
86     assertEquals(2, cs.absoluteToVisibleColumn(5));
87
88     // check with > 1 hidden column regions
89     // where some columns are in the hidden regions
90     HiddenColumns cs2 = new HiddenColumns();
91     cs2.hideColumns(5, 10);
92     cs2.hideColumns(20, 27);
93     cs2.hideColumns(40, 44);
94
95     // hiding columns 5-10 and 20-27 moves column 8 to column 4
96     assertEquals(4, cs2.absoluteToVisibleColumn(8));
97
98     // and moves column 24 to 13
99     assertEquals(13, cs2.absoluteToVisibleColumn(24));
100
101     // and moves column 28 to 14
102     assertEquals(14, cs2.absoluteToVisibleColumn(28));
103
104     // and moves column 40 to 25
105     assertEquals(25, cs2.absoluteToVisibleColumn(40));
106
107     // check when hidden columns start at 0 that the visible column
108     // is returned as 0
109     HiddenColumns cs3 = new HiddenColumns();
110     cs3.hideColumns(0, 4);
111     assertEquals(0, cs3.absoluteToVisibleColumn(2));
112
113     // check that column after the last hidden region doesn't crash
114     assertEquals(46, cs2.absoluteToVisibleColumn(65));
115   }
116
117   @Test(groups = { "Functional" })
118   public void testVisibleContigsIterator()
119   {
120     HiddenColumns cs = new HiddenColumns();
121
122     Iterator<int[]> visible = cs.getVisContigsIterator(3, 10, false);
123     int[] region = visible.next();
124     assertEquals("[3, 9]", Arrays.toString(region));
125     assertFalse(visible.hasNext());
126
127     cs.hideColumns(3, 6);
128     cs.hideColumns(8, 9);
129     cs.hideColumns(12, 12);
130
131     // Test both ends visible region
132
133     // start position is inclusive, end position exclusive
134     visible = cs.getVisContigsIterator(1, 13, false);
135     region = visible.next();
136     assertEquals("[1, 2]", Arrays.toString(region));
137     region = visible.next();
138     assertEquals("[7, 7]", Arrays.toString(region));
139     region = visible.next();
140     assertEquals("[10, 11]", Arrays.toString(region));
141     assertFalse(visible.hasNext());
142
143     // Test start hidden, end visible
144     visible = cs.getVisContigsIterator(4, 14, false);
145     region = visible.next();
146     assertEquals("[7, 7]", Arrays.toString(region));
147     region = visible.next();
148     assertEquals("[10, 11]", Arrays.toString(region));
149     region = visible.next();
150     assertEquals("[13, 13]", Arrays.toString(region));
151     assertFalse(visible.hasNext());
152
153     // Test start hidden, end hidden
154     visible = cs.getVisContigsIterator(3, 10, false);
155     region = visible.next();
156     assertEquals("[7, 7]", Arrays.toString(region));
157     assertFalse(visible.hasNext());
158
159     // Test start visible, end hidden
160     visible = cs.getVisContigsIterator(0, 13, false);
161     region = visible.next();
162     assertEquals("[0, 2]", Arrays.toString(region));
163     region = visible.next();
164     assertEquals("[7, 7]", Arrays.toString(region));
165     region = visible.next();
166     assertEquals("[10, 11]", Arrays.toString(region));
167     assertFalse(visible.hasNext());
168
169     // Test empty result
170     visible = cs.getVisContigsIterator(4, 6, false);
171     assertFalse(visible.hasNext());
172   }
173
174   @Test(groups = { "Functional" })
175   public void testEquals()
176   {
177     HiddenColumns cs = new HiddenColumns();
178     cs.hideColumns(5, 9);
179
180     // a different set of hidden columns
181     HiddenColumns cs2 = new HiddenColumns();
182
183     // with no hidden columns
184     assertFalse(cs.equals(cs2));
185     assertFalse(cs2.equals(cs));
186
187     // with the wrong kind of object
188     assertFalse(cs.equals(new HiddenColumnsCursor()));
189
190     // with a different hiddenColumns object - by size
191     HiddenColumns cs3 = new HiddenColumns();
192     cs3.hideColumns(2, 3);
193     assertFalse(cs.equals(cs3));
194
195     // with hidden columns added in a different order
196     cs2.hideColumns(6, 9);
197     assertFalse(cs.equals(cs2));
198     assertFalse(cs2.equals(cs));
199
200     cs2.hideColumns(5, 8);
201
202     assertTrue(cs.equals(cs2));
203     assertTrue(cs.equals(cs));
204     assertTrue(cs2.equals(cs));
205     assertTrue(cs2.equals(cs2));
206
207     // different ranges, same size
208     cs.hideColumns(10, 12);
209     cs2.hideColumns(10, 15);
210     assertFalse(cs.equals(cs2));
211
212   }
213
214   @Test(groups = "Functional")
215   public void testCopyConstructor()
216   {
217     HiddenColumns cs = new HiddenColumns();
218     cs.hideColumns(10, 11);
219     cs.hideColumns(5, 7);
220     Iterator<int[]> regions = cs.iterator();
221     assertEquals("[5, 7]",
222             Arrays.toString(regions.next()));
223
224     HiddenColumns cs2 = new HiddenColumns(cs);
225     regions = cs2.iterator();
226     assertTrue(cs2.hasHiddenColumns());
227     assertEquals(2, cs2.getNumberOfRegions());
228     // hidden columns are held in column order
229     assertEquals("[5, 7]",
230             Arrays.toString(regions.next()));
231     assertEquals("[10, 11]",
232             Arrays.toString(regions.next()));
233   }
234
235   @Test(groups = "Functional")
236   public void testCopyConstructor2()
237   {
238     HiddenColumns cs = new HiddenColumns();
239     cs.hideColumns(10, 11);
240     cs.hideColumns(5, 7);
241
242     HiddenColumns cs2 = new HiddenColumns(cs, 3, 9, 1);
243     assertTrue(cs2.hasHiddenColumns());
244     Iterator<int[]> regions = cs2.iterator();
245
246     // only [5,7] returned, offset by 1
247     assertEquals("[4, 6]",
248             Arrays.toString(regions.next()));
249     assertEquals(3, cs2.getSize());
250
251     cs2 = new HiddenColumns(cs, 8, 15, 4);
252     regions = cs2.iterator();
253     assertTrue(cs2.hasHiddenColumns());
254
255     // only [10,11] returned, offset by 4
256     assertEquals("[6, 7]",
257             Arrays.toString(regions.next()));
258     assertEquals(2, cs2.getSize());
259
260     cs2 = new HiddenColumns(cs, 6, 10, 4);
261     assertFalse(cs2.hasHiddenColumns());
262   }
263
264   /**
265    * Test the code used to locate the reference sequence ruler origin
266    */
267   @Test(groups = { "Functional" })
268   public void testLocateVisibleStartofSequence()
269   {
270     // create random alignment
271     AlignmentGenerator gen = new AlignmentGenerator(false);
272     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
273
274     HiddenColumns cs = al.getHiddenColumns();
275     ColumnSelection colsel = new ColumnSelection();
276
277     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
278     assertEquals(2, seq.findIndex(seq.getStart()));
279
280     // no hidden columns
281     assertEquals(seq.findIndex(seq.getStart()) - 1, cs.locateVisibleStartOfSequence(seq));
282
283     // hidden column on gap after end of sequence - should not affect bounds
284     colsel.hideSelectedColumns(13, al.getHiddenColumns());
285     assertEquals(seq.findIndex(seq.getStart()) - 1,cs.locateVisibleStartOfSequence(seq));
286
287     cs.revealAllHiddenColumns(colsel);
288     // hidden column on gap before beginning of sequence - should vis bounds by
289     // one
290     colsel.hideSelectedColumns(0, al.getHiddenColumns());
291     assertEquals(seq.findIndex(seq.getStart()) - 2,cs.locateVisibleStartOfSequence(seq));
292
293     cs.revealAllHiddenColumns(colsel);
294     // hide columns around most of sequence - leave one residue remaining
295     cs.hideColumns(1, 3);
296     cs.hideColumns(6, 11);
297     assertEquals("-D",
298             cs.getVisibleSequenceStrings(0, 5, new SequenceI[]
299     { seq })[0]);
300
301     assertEquals(1, cs.locateVisibleStartOfSequence(seq));
302     cs.revealAllHiddenColumns(colsel);
303
304     // hide whole sequence - should just get location of hidden region
305     // containing sequence
306     cs.hideColumns(1, 11);
307     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
308
309     cs.revealAllHiddenColumns(colsel);
310     cs.hideColumns(0, 15);
311     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
312
313     SequenceI seq2 = new Sequence("RefSeq2", "-------A-SD-ASD--E---");
314
315     cs.revealAllHiddenColumns(colsel);
316     cs.hideColumns(7, 17);
317     assertEquals(0,cs.locateVisibleStartOfSequence(seq2));
318
319     cs.revealAllHiddenColumns(colsel);
320     cs.hideColumns(3, 17);
321     assertEquals(0,cs.locateVisibleStartOfSequence(seq2));
322
323     cs.revealAllHiddenColumns(colsel);
324     cs.hideColumns(3, 19);
325     assertEquals(0,cs.locateVisibleStartOfSequence(seq2));
326
327     cs.revealAllHiddenColumns(colsel);
328     cs.hideColumns(0, 0);
329     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
330
331     cs.revealAllHiddenColumns(colsel);
332     cs.hideColumns(0, 1);
333     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
334
335     cs.revealAllHiddenColumns(colsel);
336     cs.hideColumns(0, 2);
337     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
338
339     cs.revealAllHiddenColumns(colsel);
340     cs.hideColumns(1, 1);
341     assertEquals(2,cs.locateVisibleStartOfSequence(seq));
342
343     cs.revealAllHiddenColumns(colsel);
344     cs.hideColumns(1, 2);
345     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
346
347     cs.revealAllHiddenColumns(colsel);
348     cs.hideColumns(1, 3);
349     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
350
351     cs.revealAllHiddenColumns(colsel);
352     cs.hideColumns(0, 2);
353     cs.hideColumns(5, 6);
354     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
355
356     cs.revealAllHiddenColumns(colsel);
357     cs.hideColumns(0, 2);
358     cs.hideColumns(5, 6);
359     cs.hideColumns(9, 10);
360     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
361
362     cs.revealAllHiddenColumns(colsel);
363     cs.hideColumns(0, 2);
364     cs.hideColumns(7, 11);
365     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
366
367     cs.revealAllHiddenColumns(colsel);
368     cs.hideColumns(2, 4);
369     cs.hideColumns(7, 11);
370     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
371
372     cs.revealAllHiddenColumns(colsel);
373     cs.hideColumns(2, 4);
374     cs.hideColumns(7, 12);
375     assertEquals(1,cs.locateVisibleStartOfSequence(seq));
376
377     cs.revealAllHiddenColumns(colsel);
378     cs.hideColumns(1, 11);
379     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
380
381     cs.revealAllHiddenColumns(colsel);
382     cs.hideColumns(0, 12);
383     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
384
385     cs.revealAllHiddenColumns(colsel);
386     cs.hideColumns(0, 4);
387     cs.hideColumns(6, 12);
388     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
389
390     cs.revealAllHiddenColumns(colsel);
391     cs.hideColumns(0, 1);
392     cs.hideColumns(3, 12);
393     assertEquals(0,cs.locateVisibleStartOfSequence(seq));
394
395     cs.revealAllHiddenColumns(colsel);
396     cs.hideColumns(3, 14);
397     cs.hideColumns(17, 19);
398     assertEquals(3,cs.locateVisibleStartOfSequence(seq2));
399
400     cs.revealAllHiddenColumns(colsel);
401     cs.hideColumns(3, 7);
402     cs.hideColumns(9, 14);
403     cs.hideColumns(17, 19);
404     assertEquals(9,cs.locateVisibleStartOfSequence(seq2));
405
406     cs.revealAllHiddenColumns(colsel);
407     cs.hideColumns(0, 1);
408     cs.hideColumns(3, 4);
409     cs.hideColumns(6, 8);
410     cs.hideColumns(10, 12);
411     assertEquals(6, cs.locateVisibleStartOfSequence(seq));
412
413   }
414
415   @Test(groups = { "Functional" })
416   public void testLocateVisibleStartPathologicals()
417   {
418     // test some pathological cases we missed
419     AlignmentI al = new Alignment(
420             new SequenceI[]
421     { new Sequence("refseqGaptest", "KTDVTI----------NFI-----G----L") });
422     HiddenColumns cs = new HiddenColumns();
423     cs.hideList(al.getSequenceAt(0).getInsertions());
424     assertEquals("G", ""
425             + al.getSequenceAt(0).getCharAt(cs.visibleToAbsoluteColumn(9)));
426
427     // KM: no idea what this is meant to be testing... seems to be an unfinished
428     // test
429   }
430
431   @Test(groups = { "Functional" })
432   public void testHideColumns()
433   {
434     // create random alignment
435     AlignmentGenerator gen = new AlignmentGenerator(false);
436     AlignmentI al = gen.generate(50, 20, 123, 5, 5);
437
438     ColumnSelection colsel = new ColumnSelection();
439     HiddenColumns cs = al.getHiddenColumns();
440     colsel.hideSelectedColumns(5, al.getHiddenColumns());
441     Iterator<int[]> regions = cs.iterator();
442     assertEquals(1, cs.getNumberOfRegions());
443     assertEquals("[5, 5]", Arrays.toString(regions.next()));
444
445     colsel.hideSelectedColumns(3, al.getHiddenColumns());
446     regions = cs.iterator();
447     assertEquals(2, cs.getNumberOfRegions());
448     // two hidden ranges, in order:
449     assertEquals("[3, 3]", Arrays.toString(regions.next()));
450     assertEquals("[5, 5]", Arrays.toString(regions.next()));
451
452     // hiding column 4 expands [3, 3] to [3, 4]
453     // and merges to [5, 5] to make [3, 5]
454     colsel.hideSelectedColumns(4, al.getHiddenColumns());
455     regions = cs.iterator();
456     assertEquals(1, cs.getNumberOfRegions());
457     assertEquals("[3, 5]", Arrays.toString(regions.next()));
458
459     // clear hidden columns (note they are added to selected)
460     cs.revealAllHiddenColumns(colsel);
461     // it is now actually null but getter returns an empty list
462     assertEquals(0, cs.getNumberOfRegions());
463
464     cs.hideColumns(3, 6);
465     regions = cs.iterator();
466     int[] firstHiddenRange = regions.next();
467     assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
468
469     // adding a subrange of already hidden should do nothing
470     cs.hideColumns(4, 5);
471     regions = cs.iterator();
472     assertEquals(1, cs.getNumberOfRegions());
473     assertEquals("[3, 6]",
474             Arrays.toString(regions.next()));
475     cs.hideColumns(3, 5);
476     regions = cs.iterator();
477     assertEquals(1, cs.getNumberOfRegions());
478     assertEquals("[3, 6]",
479             Arrays.toString(regions.next()));
480     cs.hideColumns(4, 6);
481     regions = cs.iterator();
482     assertEquals(1, cs.getNumberOfRegions());
483     assertEquals("[3, 6]",
484             Arrays.toString(regions.next()));
485     cs.hideColumns(3, 6);
486     regions = cs.iterator();
487     assertEquals(1, cs.getNumberOfRegions());
488     assertEquals("[3, 6]",
489             Arrays.toString(regions.next()));
490
491     cs.revealAllHiddenColumns(colsel);
492     cs.hideColumns(2, 4);
493     regions = cs.iterator();
494     assertEquals(1, cs.getNumberOfRegions());
495     assertEquals("[2, 4]", Arrays.toString(regions.next()));
496
497     // extend contiguous with 2 positions overlap
498     cs.hideColumns(3, 5);
499     regions = cs.iterator();
500     assertEquals(1, cs.getNumberOfRegions());
501     assertEquals("[2, 5]", Arrays.toString(regions.next()));
502
503     // extend contiguous with 1 position overlap
504     cs.hideColumns(5, 6);
505     regions = cs.iterator();
506     assertEquals(1, cs.getNumberOfRegions());
507     assertEquals("[2, 6]", Arrays.toString(regions.next()));
508
509     // extend contiguous with overlap both ends:
510     cs.hideColumns(1, 7);
511     regions = cs.iterator();
512     assertEquals(1, cs.getNumberOfRegions());
513     assertEquals("[1, 7]", Arrays.toString(regions.next()));
514
515     cs.revealAllHiddenColumns(colsel);
516     cs.hideColumns(15, 18);
517     cs.hideColumns(2, 4);
518     cs.hideColumns(7, 9);
519     regions = cs.iterator();
520     assertEquals(3, cs.getNumberOfRegions());
521     assertEquals("[2, 4]", Arrays.toString(regions.next()));
522     assertEquals("[7, 9]", Arrays.toString(regions.next()));
523     assertEquals("[15, 18]", Arrays.toString(regions.next()));
524   }
525
526   /**
527    * Test the method that reveals a range of hidden columns given the start
528    * column of the range
529    */
530   @Test(groups = { "Functional" })
531   public void testRevealHiddenColumns()
532   {
533     ColumnSelection colsel = new ColumnSelection();
534     HiddenColumns cs = new HiddenColumns();
535
536     // test with null hidden columns
537     cs.revealHiddenColumns(5, colsel);
538     assertTrue(colsel.getSelected().isEmpty());
539
540     cs.hideColumns(5, 8);
541     colsel.addElement(10);
542     cs.revealHiddenColumns(5, colsel);
543
544     // hiddenColumns now empty
545     assertEquals(0, cs.getSize());
546
547     // revealed columns are marked as selected (added to selection):
548     assertEquals("[10, 5, 6, 7, 8]", colsel.getSelected().toString());
549
550     // calling with a column other than the range start does nothing:
551     colsel = new ColumnSelection();
552     cs = new HiddenColumns();
553     cs.hideColumns(5, 8);
554
555     int prevSize = cs.getSize();
556     cs.revealHiddenColumns(6, colsel);
557     assertEquals(prevSize, cs.getSize());
558     assertTrue(colsel.getSelected().isEmpty());
559
560     // reveal hidden columns when there is more than one region
561     cs.hideColumns(20, 23);
562     // now there are 2 hidden regions
563     assertEquals(2, cs.getNumberOfRegions());
564
565     cs.revealHiddenColumns(20, colsel);
566
567     // hiddenColumns now has one region
568     assertEquals(1, cs.getNumberOfRegions());
569
570     // revealed columns are marked as selected (added to selection):
571     assertEquals("[20, 21, 22, 23]", colsel.getSelected().toString());
572
573     // call with a column past the end of the hidden column ranges
574     colsel.clear();
575     cs.revealHiddenColumns(20, colsel);
576     // hiddenColumns still has 1 region
577     assertEquals(1, cs.getNumberOfRegions());
578     assertTrue(colsel.getSelected().isEmpty());
579   }
580
581   @Test(groups = { "Functional" })
582   public void testRevealAllHiddenColumns()
583   {
584     HiddenColumns hidden = new HiddenColumns();
585     ColumnSelection colsel = new ColumnSelection();
586
587     // test with null hidden columns
588     hidden.revealAllHiddenColumns(colsel);
589     assertTrue(colsel.getSelected().isEmpty());
590
591     hidden.hideColumns(5, 8);
592     hidden.hideColumns(2, 3);
593     colsel.addElement(11);
594     colsel.addElement(1);
595     hidden.revealAllHiddenColumns(colsel);
596
597     /*
598      * revealing hidden columns adds them (in order) to the (unordered)
599      * selection list
600      */
601
602     // hiddenColumns now empty
603     assertEquals(0, hidden.getSize());
604
605     assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]",
606             colsel.getSelected().toString());
607   }
608
609   @Test(groups = { "Functional" })
610   public void testIsVisible()
611   {
612     HiddenColumns cs = new HiddenColumns();
613     cs.hideColumns(2, 4);
614     cs.hideColumns(6, 7);
615     assertTrue(cs.isVisible(0));
616     assertTrue(cs.isVisible(-99));
617     assertTrue(cs.isVisible(1));
618     assertFalse(cs.isVisible(2));
619     assertFalse(cs.isVisible(3));
620     assertFalse(cs.isVisible(4));
621     assertTrue(cs.isVisible(5));
622     assertFalse(cs.isVisible(6));
623     assertFalse(cs.isVisible(7));
624     assertTrue(cs.isVisible(8));
625   }
626
627   /**
628    * Test for the case when a hidden range encloses more one already hidden
629    * range
630    */
631   @Test(groups = { "Functional" })
632   public void testHideColumns_subsumingHidden()
633   {
634     /*
635      * JAL-2370 bug scenario:
636      * two hidden ranges subsumed by a third
637      */
638     HiddenColumns cs = new HiddenColumns();
639     cs.hideColumns(49, 59);
640     cs.hideColumns(69, 79);
641     Iterator<int[]> regions = cs.iterator();
642     assertEquals(2, cs.getNumberOfRegions());
643     assertEquals("[49, 59]", Arrays.toString(regions.next()));
644     assertEquals("[69, 79]", Arrays.toString(regions.next()));
645
646     cs.hideColumns(48, 80);
647     regions = cs.iterator();
648     assertEquals(1, cs.getNumberOfRegions());
649     assertEquals("[48, 80]", Arrays.toString(regions.next()));
650
651     /*
652      * another...joining hidden ranges
653      */
654     cs = new HiddenColumns();
655     cs.hideColumns(10, 20);
656     cs.hideColumns(30, 40);
657     cs.hideColumns(50, 60);
658     // hiding 21-49 should merge to one range
659     cs.hideColumns(21, 49);
660     regions = cs.iterator();
661     assertEquals(1, cs.getNumberOfRegions());
662     assertEquals("[10, 60]", Arrays.toString(regions.next()));
663
664     /*
665      * another...left overlap, subsumption, right overlap,
666      * no overlap of existing hidden ranges
667      */
668     cs = new HiddenColumns();
669     cs.hideColumns(10, 20);
670     cs.hideColumns(10, 20);
671     cs.hideColumns(30, 35);
672     cs.hideColumns(40, 50);
673     cs.hideColumns(60, 70);
674
675     cs.hideColumns(15, 45);
676     regions = cs.iterator();
677     assertEquals(2, cs.getNumberOfRegions());
678     assertEquals("[10, 50]", Arrays.toString(regions.next()));
679     assertEquals("[60, 70]", Arrays.toString(regions.next()));
680   }
681
682   @Test(groups = { "Functional" })
683   public void testHideBitset()
684   {
685     HiddenColumns cs;
686
687     BitSet one = new BitSet();
688
689     // one hidden range
690     one.set(1);
691     cs = new HiddenColumns();
692     cs.hideColumns(one);
693     assertEquals(1, cs.getNumberOfRegions());
694
695     one.set(2);
696     cs = new HiddenColumns();
697     cs.hideColumns(one);
698     assertEquals(1, cs.getNumberOfRegions());
699
700     one.set(3);
701     cs = new HiddenColumns();
702     cs.hideColumns(one);
703     assertEquals(1, cs.getNumberOfRegions());
704
705     // split
706     one.clear(2);
707     cs = new HiddenColumns();
708     cs.hideColumns(one);
709     assertEquals(2, cs.getNumberOfRegions());
710
711     assertEquals(0, cs.visibleToAbsoluteColumn(0));
712     assertEquals(2, cs.visibleToAbsoluteColumn(1));
713     assertEquals(4, cs.visibleToAbsoluteColumn(2));
714
715     // one again
716     one.clear(1);
717     cs = new HiddenColumns();
718     cs.hideColumns(one);
719
720     assertEquals(1, cs.getNumberOfRegions());
721
722     assertEquals(0, cs.visibleToAbsoluteColumn(0));
723     assertEquals(1, cs.visibleToAbsoluteColumn(1));
724     assertEquals(2, cs.visibleToAbsoluteColumn(2));
725     assertEquals(4, cs.visibleToAbsoluteColumn(3));
726   }
727
728   @Test(groups = { "Functional" })
729   public void testMarkHiddenRegions()
730   {
731     BitSet toMark, fromMark;
732     long seed = -3241532;
733     Random number = new Random(seed);
734     for (int n = 0; n < 1000; n++)
735     {
736       // create a random bitfield
737       toMark = BitSet
738               .valueOf(new long[]
739       { number.nextLong(), number.nextLong(), number.nextLong() });
740       toMark.set(n * number.nextInt(10), n * (25 + number.nextInt(25)));
741       HiddenColumns hc = new HiddenColumns();
742
743       if (n == 0)
744       {
745         hc.markHiddenRegions(fromMark = new BitSet());
746         assertTrue(fromMark.isEmpty());
747       }
748
749       hc.hideColumns(toMark);
750
751       // see if we can recover bitfield
752       hc.markHiddenRegions(fromMark = new BitSet());
753       assertEquals(toMark, fromMark);
754     }
755   }
756
757   @Test(groups = { "Functional" })
758   public void testRegionsToString()
759   {
760     HiddenColumns hc = new HiddenColumns();
761
762     String result = hc.regionsToString(",", "--");
763     assertEquals("", result);
764
765     hc.hideColumns(3, 7);
766     hc.hideColumns(10, 10);
767     hc.hideColumns(14, 15);
768
769     result = hc.regionsToString(",", "--");
770     assertEquals("3--7,10--10,14--15", result);
771   }
772
773   @Test(groups = "Functional")
774   public void testGetVisibleStartAndEndIndex()
775   {
776     Sequence seq = new Sequence("testSeq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
777     AlignmentI align = new Alignment(new SequenceI[] { seq });
778     HiddenColumns hc = new HiddenColumns();
779
780     int[] startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
781     assertEquals(0, startEnd[0]);
782     assertEquals(25, startEnd[1]);
783
784     hc.hideColumns(0, 0);
785     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
786     assertEquals(1, startEnd[0]);
787     assertEquals(25, startEnd[1]);
788
789     hc.hideColumns(6, 9);
790     hc.hideColumns(11, 12);
791     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
792     assertEquals(1, startEnd[0]);
793     assertEquals(25, startEnd[1]);
794
795     hc.hideColumns(24, 25);
796     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
797     System.out.println(startEnd[0] + " : " + startEnd[1]);
798     assertEquals(1, startEnd[0]);
799     assertEquals(23, startEnd[1]);
800
801     // force lowest range to start of alignment
802     hc = new HiddenColumns();
803     hc.hideColumns(3, 4);
804     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
805     assertEquals(0, startEnd[0]);
806     assertEquals(25, startEnd[1]);
807   }
808
809   @Test(groups = "Functional")
810   public void testGetRegionWithEdgeAtRes()
811   {
812     HiddenColumns hc = new HiddenColumns();
813
814     int[] result = hc.getRegionWithEdgeAtRes(5);
815     assertNull(result);
816
817     hc.hideColumns(3, 7);
818     hc.hideColumns(10, 10);
819     hc.hideColumns(14, 15);
820
821     result = hc.getRegionWithEdgeAtRes(2);
822     assertEquals(3, result[0]);
823     assertEquals(7, result[1]);
824
825     result = hc.getRegionWithEdgeAtRes(4);
826     assertEquals(10, result[0]);
827     assertEquals(10, result[1]);
828
829     result = hc.getRegionWithEdgeAtRes(5);
830     assertEquals(10, result[0]);
831     assertEquals(10, result[1]);
832
833     result = hc.getRegionWithEdgeAtRes(6);
834     assertNull(result);
835
836     result = hc.getRegionWithEdgeAtRes(0);
837     assertNull(result);
838
839     result = hc.getRegionWithEdgeAtRes(7);
840     assertEquals(14, result[0]);
841     assertEquals(15, result[1]);
842
843     result = hc.getRegionWithEdgeAtRes(8);
844     assertEquals(14, result[0]);
845     assertEquals(15, result[1]);
846
847     result = hc.getRegionWithEdgeAtRes(16);
848     assertNull(result);
849   }
850
851   @Test(groups = "Functional")
852   public void testPropagateInsertions()
853   {
854     // create an alignment with no gaps - this will be the profile seq and other
855     // JPRED seqs
856     AlignmentGenerator gen = new AlignmentGenerator(false);
857     AlignmentI al = gen.generate(25, 10, 1234, 0, 0);
858
859     // get the profileseq
860     SequenceI profileseq = al.getSequenceAt(0);
861     SequenceI gappedseq = new Sequence(profileseq);
862     gappedseq.insertCharAt(5, al.getGapCharacter());
863     gappedseq.insertCharAt(6, al.getGapCharacter());
864     gappedseq.insertCharAt(7, al.getGapCharacter());
865     gappedseq.insertCharAt(8, al.getGapCharacter());
866
867     // force different kinds of padding
868     al.getSequenceAt(3).deleteChars(2, 23);
869     al.getSequenceAt(4).deleteChars(2, 27);
870     al.getSequenceAt(5).deleteChars(10, 27);
871
872     // create an alignment view with the gapped sequence
873     SequenceI[] seqs = new SequenceI[1];
874     seqs[0] = gappedseq;
875     AlignmentI newal = new Alignment(seqs);
876     HiddenColumns hidden = new HiddenColumns();
877     hidden.hideColumns(15, 17);
878
879     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
880             false);
881
882     // confirm that original contigs are as expected
883     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 25, false);
884     int[] region = visible.next();
885     assertEquals("[0, 14]", Arrays.toString(region));
886     region = visible.next();
887     assertEquals("[18, 24]", Arrays.toString(region));
888
889     // propagate insertions
890     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
891             view);
892
893     // confirm that the contigs have changed to account for the gaps
894     visible = result.getVisContigsIterator(0, 25, false);
895     region = visible.next();
896     assertEquals("[0, 10]", Arrays.toString(region));
897     region = visible.next();
898     assertEquals("[14, 24]", Arrays.toString(region));
899
900     // confirm the alignment has been changed so that the other sequences have
901     // gaps inserted where the columns are hidden
902     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[10]));
903     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[11]));
904     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[12]));
905     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[13]));
906     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[14]));
907
908   }
909
910   @Test(groups = "Functional")
911   public void testPropagateInsertionsOverlap()
912   {
913     // test propagateInsertions where gaps and hiddenColumns overlap
914
915     // create an alignment with no gaps - this will be the profile seq and other
916     // JPRED seqs
917     AlignmentGenerator gen = new AlignmentGenerator(false);
918     AlignmentI al = gen.generate(20, 10, 1234, 0, 0);
919
920     // get the profileseq
921     SequenceI profileseq = al.getSequenceAt(0);
922     SequenceI gappedseq = new Sequence(profileseq);
923     gappedseq.insertCharAt(5, al.getGapCharacter());
924     gappedseq.insertCharAt(6, al.getGapCharacter());
925     gappedseq.insertCharAt(7, al.getGapCharacter());
926     gappedseq.insertCharAt(8, al.getGapCharacter());
927
928     // create an alignment view with the gapped sequence
929     SequenceI[] seqs = new SequenceI[1];
930     seqs[0] = gappedseq;
931     AlignmentI newal = new Alignment(seqs);
932
933     // hide columns so that some overlap with the gaps
934     HiddenColumns hidden = new HiddenColumns();
935     hidden.hideColumns(7, 10);
936
937     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
938             false);
939
940     // confirm that original contigs are as expected
941     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 20, false);
942     int[] region = visible.next();
943     assertEquals("[0, 6]", Arrays.toString(region));
944     region = visible.next();
945     assertEquals("[11, 19]", Arrays.toString(region));
946     assertFalse(visible.hasNext());
947
948     // propagate insertions
949     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
950             view);
951
952     // confirm that the contigs have changed to account for the gaps
953     visible = result.getVisContigsIterator(0, 20, false);
954     region = visible.next();
955     assertEquals("[0, 4]", Arrays.toString(region));
956     region = visible.next();
957     assertEquals("[7, 19]", Arrays.toString(region));
958     assertFalse(visible.hasNext());
959
960     // confirm the alignment has been changed so that the other sequences have
961     // gaps inserted where the columns are hidden
962     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[4]));
963     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[5]));
964     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[6]));
965     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[7]));
966   }
967
968   @Test(groups = "Functional")
969   public void testHasHiddenColumns()
970   {
971     HiddenColumns h = new HiddenColumns();
972
973     // new HiddenColumns2 has no hidden cols
974     assertFalse(h.hasHiddenColumns());
975
976     // some columns hidden, returns true
977     h.hideColumns(5, 10);
978     assertTrue(h.hasHiddenColumns());
979
980     // reveal columns, no hidden cols again
981     ColumnSelection sel = new ColumnSelection();
982     h.revealAllHiddenColumns(sel);
983     assertFalse(h.hasHiddenColumns());
984   }
985
986   @Test(groups = "Functional")
987   public void testHasManyHiddenColumns()
988   {
989     HiddenColumns h = new HiddenColumns();
990
991     // h has no hidden cols
992     assertFalse(h.hasMultiHiddenColumnRegions());
993
994     // one set of columns hidden, returns false
995     h.hideColumns(5, 10);
996     assertFalse(h.hasMultiHiddenColumnRegions());
997
998     // two sets hidden, returns true
999     h.hideColumns(15, 17);
1000     assertTrue(h.hasMultiHiddenColumnRegions());
1001
1002     // back to one block, asserts false
1003     h.hideColumns(11, 14);
1004     assertFalse(h.hasMultiHiddenColumnRegions());
1005   }
1006
1007   @Test(groups = "Functional")
1008   public void testAdjustForHiddenColumns()
1009   {
1010     HiddenColumns h = new HiddenColumns();
1011     // returns input value when there are no hidden columns
1012     assertEquals(10, h.visibleToAbsoluteColumn(10));
1013
1014     h.hideColumns(20, 30);
1015     assertEquals(10, h.visibleToAbsoluteColumn(10));
1016     assertEquals(20 + 11, h.visibleToAbsoluteColumn(20));
1017     assertEquals(35 + 11, h.visibleToAbsoluteColumn(35));
1018
1019     h.hideColumns(5, 7);
1020     assertEquals(10 + 3, h.visibleToAbsoluteColumn(10));
1021     assertEquals(20 + 14, h.visibleToAbsoluteColumn(20));
1022     assertEquals(35 + 14, h.visibleToAbsoluteColumn(35));
1023
1024     ColumnSelection sel = new ColumnSelection();
1025     h.revealAllHiddenColumns(sel);
1026     h.hideColumns(0, 1);
1027     assertEquals(4, h.visibleToAbsoluteColumn(2));
1028   }
1029
1030   @Test(groups = "Functional")
1031   public void testGetHiddenBoundaryLeft()
1032   {
1033     HiddenColumns h = new HiddenColumns();
1034
1035     // returns same value if no hidden cols
1036     assertEquals(3, h.getHiddenBoundaryLeft(3));
1037
1038     h.hideColumns(5, 10);
1039     assertEquals(10, h.getHiddenBoundaryLeft(15));
1040     assertEquals(3, h.getHiddenBoundaryLeft(3));
1041     assertEquals(7, h.getHiddenBoundaryLeft(7));
1042
1043     h.hideColumns(15, 20);
1044     assertEquals(10, h.getHiddenBoundaryLeft(15));
1045     assertEquals(20, h.getHiddenBoundaryLeft(21));
1046   }
1047
1048   @Test(groups = "Functional")
1049   public void testGetHiddenBoundaryRight()
1050   {
1051     HiddenColumns h = new HiddenColumns();
1052
1053     // returns same value if no hidden cols
1054     assertEquals(3, h.getHiddenBoundaryRight(3));
1055
1056     h.hideColumns(5, 10);
1057     assertEquals(5, h.getHiddenBoundaryRight(3));
1058     assertEquals(15, h.getHiddenBoundaryRight(15));
1059     assertEquals(7, h.getHiddenBoundaryRight(7));
1060
1061     h.hideColumns(15, 20);
1062     assertEquals(15, h.getHiddenBoundaryRight(7));
1063     assertEquals(15, h.getHiddenBoundaryRight(14));
1064
1065     // returns same value if there is no next hidden column
1066     assertEquals(22, h.getHiddenBoundaryRight(22));
1067   }
1068
1069   @Test(groups = "Functional")
1070   public void testIterator()
1071   {
1072     HiddenColumns h = new HiddenColumns();
1073     Iterator<int[]> result = h.iterator();
1074     assertFalse(result.hasNext());
1075
1076     h.hideColumns(5, 10);
1077     result = h.iterator();
1078     int[] next = result.next();
1079     assertEquals(5, next[0]);
1080     assertEquals(10, next[1]);
1081     assertFalse(result.hasNext());
1082
1083     h.hideColumns(22, 23);
1084     result = h.iterator();
1085     next = result.next();
1086     assertEquals(5, next[0]);
1087     assertEquals(10, next[1]);
1088     next = result.next();
1089     assertEquals(22, next[0]);
1090     assertEquals(23, next[1]);
1091     assertFalse(result.hasNext());
1092
1093     // test for only one hidden region at start of alignment
1094     ColumnSelection sel = new ColumnSelection();
1095     h.revealAllHiddenColumns(sel);
1096     h.hideColumns(0, 1);
1097     result = h.iterator();
1098     next = result.next();
1099     assertEquals(0, next[0]);
1100     assertEquals(1, next[1]);
1101     assertFalse(result.hasNext());
1102   }
1103
1104   @Test(groups = "Functional")
1105   public void testGetVisibleSequenceStrings()
1106   {
1107     HiddenColumns h = new HiddenColumns();
1108     SequenceI seq1 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1109     SequenceI seq2 = new Sequence("TEST2", "VICYHRNDTGA");
1110     SequenceI[] seqs = new SequenceI[2];
1111     seqs[0] = seq1;
1112     seqs[1] = seq2;
1113     String[] result = h.getVisibleSequenceStrings(5, 10, seqs);
1114     assertEquals(2, result.length);
1115     assertEquals("WKQES", result[0]);
1116     assertEquals("RNDTG", result[1]);
1117
1118     h.hideColumns(6, 8);
1119     result = h.getVisibleSequenceStrings(5, 10, seqs);
1120     assertEquals(2, result.length);
1121     assertEquals("WS", result[0]);
1122     assertEquals("RG", result[1]);
1123
1124     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
1125     ColumnSelection sel = new ColumnSelection();
1126     h.revealAllHiddenColumns(sel);
1127     h.hideColumns(1, 3);
1128     h.hideColumns(6, 11);
1129     assertEquals("-D",
1130             h.getVisibleSequenceStrings(0, 5, new SequenceI[]
1131     { seq })[0]);
1132   }
1133
1134   @Test(groups = "Functional")
1135   public void testHideInsertionsFor()
1136   {
1137     HiddenColumns h = new HiddenColumns();
1138     HiddenColumns h2 = new HiddenColumns();
1139     SequenceI seq1 = new Sequence("TEST1", "GAL---MFW-KQESPVICY--HRNDT");
1140     SequenceI seq2 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1141
1142     h.hideList(seq2.getInsertions());
1143     assertTrue(h.equals(h2));
1144
1145     h.hideList(seq1.getInsertions());
1146     h2.hideColumns(3, 5);
1147     h2.hideColumns(9, 9);
1148     h2.hideColumns(19, 20);
1149     assertTrue(h.equals(h2));
1150   }
1151
1152   @Test(groups = "Functional")
1153   public void testHideMarkedBits()
1154   {
1155     HiddenColumns h = new HiddenColumns();
1156     HiddenColumns h2 = new HiddenColumns();
1157
1158     BitSet tohide = new BitSet(21);
1159     h.hideColumns(tohide);
1160     assertTrue(h.equals(h2));
1161
1162     // NB in hideMarkedBits, the last bit is not set to hidden
1163     tohide.set(3, 6);
1164     tohide.set(9);
1165     tohide.set(19, 21);
1166     h.hideColumns(tohide);
1167
1168     h2.hideColumns(3, 5);
1169     h2.hideColumns(9, 9);
1170     h2.hideColumns(19, 20);
1171     assertTrue(h.equals(h2));
1172   }
1173
1174   @Test(groups = "Functional")
1175   public void testMakeVisibleAnnotation()
1176   {
1177     HiddenColumns h = new HiddenColumns();
1178     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
1179         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1180         new Annotation(5), new Annotation(6), new Annotation(7),
1181         new Annotation(8) };
1182     AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
1183             anns);
1184
1185     // null annotation
1186     AlignmentAnnotation nullann = null;
1187     h.makeVisibleAnnotation(nullann);
1188     assertNull(nullann);
1189     
1190     h.makeVisibleAnnotation(1, 2, nullann);
1191     assertNull(nullann);
1192
1193     // null annotations
1194     AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann", null);
1195     h.makeVisibleAnnotation(emptyann);
1196     assertNull(emptyann.annotations);
1197     
1198     h.makeVisibleAnnotation(3, 4, emptyann);
1199     assertNull(emptyann.annotations);
1200
1201     // without bounds, does everything
1202     h.makeVisibleAnnotation(ann);
1203     assertEquals(12, ann.annotations.length);
1204     assertNull(ann.annotations[0]);
1205     assertNull(ann.annotations[1]);
1206     assertEquals(1.0f, ann.annotations[2].value);
1207     assertEquals(2.0f, ann.annotations[3].value);
1208     assertEquals(3.0f, ann.annotations[4].value);
1209     assertNull(ann.annotations[5]);
1210     assertNull(ann.annotations[6]);
1211     assertEquals(4.0f, ann.annotations[7].value);
1212     assertEquals(5.0f, ann.annotations[8].value);
1213     assertEquals(6.0f, ann.annotations[9].value);
1214     assertEquals(7.0f, ann.annotations[10].value);
1215     assertEquals(8.0f, ann.annotations[11].value);
1216
1217     // without hidden cols, just truncates
1218     h.makeVisibleAnnotation(3, 5, ann);
1219     assertEquals(3, ann.annotations.length);
1220     assertEquals(2.0f, ann.annotations[0].value);
1221     assertEquals(3.0f, ann.annotations[1].value);
1222     assertNull(ann.annotations[2]);
1223
1224     anns = new Annotation[] { null, null, new Annotation(1),
1225         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1226         new Annotation(5), new Annotation(6), new Annotation(7),
1227         new Annotation(8) };
1228     ann = new AlignmentAnnotation("an", "some an", anns);
1229     h.hideColumns(4, 7);
1230     h.makeVisibleAnnotation(1, 9, ann);
1231     assertEquals(5, ann.annotations.length);
1232     assertNull(ann.annotations[0]);
1233     assertEquals(1.0f, ann.annotations[1].value);
1234     assertEquals(2.0f, ann.annotations[2].value);
1235     assertEquals(5.0f, ann.annotations[3].value);
1236     assertEquals(6.0f, ann.annotations[4].value);
1237
1238     anns = new Annotation[] { null, null, new Annotation(1),
1239         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1240         new Annotation(5), new Annotation(6), new Annotation(7),
1241         new Annotation(8) };
1242     ann = new AlignmentAnnotation("an", "some an", anns);
1243     h.hideColumns(1, 2);
1244     h.makeVisibleAnnotation(1, 9, ann);
1245     assertEquals(3, ann.annotations.length);
1246     assertEquals(2.0f, ann.annotations[0].value);
1247     assertEquals(5.0f, ann.annotations[1].value);
1248     assertEquals(6.0f, ann.annotations[2].value);
1249
1250     anns = new Annotation[] { null, null, new Annotation(1),
1251         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1252         new Annotation(5), new Annotation(6), new Annotation(7),
1253         new Annotation(8), new Annotation(9), new Annotation(10),
1254         new Annotation(11), new Annotation(12), new Annotation(13),
1255         new Annotation(14), new Annotation(15) };
1256     ann = new AlignmentAnnotation("an", "some an", anns);
1257     h = new HiddenColumns();
1258     h.hideColumns(5, 18);
1259     h.hideColumns(20, 21);
1260     h.makeVisibleAnnotation(1, 21, ann);
1261     assertEquals(5, ann.annotations.length);
1262     assertEquals(1.0f, ann.annotations[1].value);
1263     assertEquals(2.0f, ann.annotations[2].value);
1264     assertEquals(3.0f, ann.annotations[3].value);
1265     assertNull(ann.annotations[0]);
1266     assertNull(ann.annotations[4]);
1267   }
1268
1269   @Test(groups = "Functional")
1270   public void testSubtractVisibleColumns()
1271   {
1272     HiddenColumns h = new HiddenColumns();
1273     int result = h.subtractVisibleColumns(1, 10);
1274     assertEquals(9, result);
1275
1276     h.hideColumns(7, 9);
1277     result = h.subtractVisibleColumns(4, 10);
1278     assertEquals(3, result);
1279
1280     h.hideColumns(14, 15);
1281     result = h.subtractVisibleColumns(4, 10);
1282     assertEquals(3, result);
1283
1284     result = h.subtractVisibleColumns(10, 17);
1285     assertEquals(2, result);
1286
1287     result = h.subtractVisibleColumns(1, 7);
1288     assertEquals(5, result);
1289
1290     result = h.subtractVisibleColumns(1, 8);
1291     assertEquals(5, result);
1292
1293     result = h.subtractVisibleColumns(3, 15);
1294     assertEquals(10, result);
1295
1296     ColumnSelection sel = new ColumnSelection();
1297     h.revealAllHiddenColumns(sel);
1298     h.hideColumns(0, 30);
1299     result = h.subtractVisibleColumns(31, 0);
1300     assertEquals(-31, result);
1301
1302     HiddenColumns cs = new HiddenColumns();
1303
1304     // test that without hidden columns, findColumnNToLeft returns
1305     // position n to left of provided position
1306     long pos = cs.subtractVisibleColumns(3, 10);
1307     assertEquals(7, pos);
1308
1309     // 0 returns same position
1310     pos = cs.subtractVisibleColumns(0, 10);
1311     assertEquals(10, pos);
1312
1313     // overflow to left returns negative number
1314     pos = cs.subtractVisibleColumns(3, 0);
1315     assertEquals(-3, pos);
1316
1317     // test that with hidden columns to left of result column
1318     // behaviour is the same as above
1319     cs.hideColumns(1, 3);
1320
1321     // position n to left of provided position
1322     pos = cs.subtractVisibleColumns(3, 10);
1323     assertEquals(7, pos);
1324
1325     // 0 returns same position
1326     pos = cs.subtractVisibleColumns(0, 10);
1327     assertEquals(10, pos);
1328
1329     // test with one set of hidden columns between start and required position
1330     cs.hideColumns(12, 15);
1331     pos = cs.subtractVisibleColumns(8, 17);
1332     assertEquals(5, pos);
1333
1334     // test with two sets of hidden columns between start and required position
1335     cs.hideColumns(20, 21);
1336     pos = cs.subtractVisibleColumns(8, 23);
1337     assertEquals(9, pos);
1338
1339     // repeat last 2 tests with no hidden columns to left of required position
1340     ColumnSelection colsel = new ColumnSelection();
1341     cs.revealAllHiddenColumns(colsel);
1342
1343     // test with one set of hidden columns between start and required position
1344     cs.hideColumns(12, 15);
1345     pos = cs.subtractVisibleColumns(8, 17);
1346     assertEquals(5, pos);
1347
1348     // test with two sets of hidden columns between start and required position
1349     cs.hideColumns(20, 21);
1350     pos = cs.subtractVisibleColumns(8, 23);
1351     assertEquals(9, pos);
1352
1353   }
1354
1355
1356   @Test(groups = "Functional")
1357   public void testBoundedIterator()
1358   {
1359     HiddenColumns h = new HiddenColumns();
1360     Iterator<int[]> it = h.getBoundedIterator(0, 10);
1361
1362     // no hidden columns = nothing to iterate over
1363     assertFalse(it.hasNext());
1364
1365     // [start,end] contains all hidden columns
1366     // all regions are returned
1367     h.hideColumns(3, 10);
1368     h.hideColumns(14, 16);
1369     it = h.getBoundedIterator(0, 20);
1370     assertTrue(it.hasNext());
1371     int[] next = it.next();
1372     assertEquals(3, next[0]);
1373     assertEquals(10, next[1]);
1374     next = it.next();
1375     assertEquals(14, next[0]);
1376     assertEquals(16, next[1]);
1377     assertFalse(it.hasNext());
1378
1379     // [start,end] overlaps a region
1380     // 1 region returned
1381     it = h.getBoundedIterator(5, 7);
1382     assertTrue(it.hasNext());
1383     next = it.next();
1384     assertEquals(3, next[0]);
1385     assertEquals(10, next[1]);
1386     assertFalse(it.hasNext());
1387
1388     // [start,end] fully contains 1 region and start of last
1389     // - 2 regions returned
1390     it = h.getBoundedIterator(3, 15);
1391     assertTrue(it.hasNext());
1392     next = it.next();
1393     assertEquals(3, next[0]);
1394     assertEquals(10, next[1]);
1395     next = it.next();
1396     assertEquals(14, next[0]);
1397     assertEquals(16, next[1]);
1398     assertFalse(it.hasNext());
1399
1400     // [start,end] contains end of first region and whole of last region
1401     // - 2 regions returned
1402     it = h.getBoundedIterator(4, 20);
1403     assertTrue(it.hasNext());
1404     next = it.next();
1405     assertEquals(3, next[0]);
1406     assertEquals(10, next[1]);
1407     next = it.next();
1408     assertEquals(14, next[0]);
1409     assertEquals(16, next[1]);
1410     assertFalse(it.hasNext());
1411   }
1412
1413   @Test(groups = "Functional")
1414   public void testBoundedStartIterator()
1415   {
1416     HiddenColumns h = new HiddenColumns();
1417     Iterator<Integer> it = h.getBoundedStartIterator(0, 10);
1418
1419     // no hidden columns = nothing to iterate over
1420     assertFalse(it.hasNext());
1421
1422     // [start,end] contains all hidden columns
1423     // all regions are returned
1424     h.hideColumns(3, 10);
1425     h.hideColumns(14, 16);
1426     it = h.getBoundedStartIterator(0, 20);
1427     assertTrue(it.hasNext());
1428     int next = it.next();
1429     assertEquals(3, next);
1430     next = it.next();
1431     assertEquals(6, next);
1432     assertFalse(it.hasNext());
1433
1434     // [start,end] does not contain a start of a region
1435     // no regions to iterate over
1436     it = h.getBoundedStartIterator(4, 5);
1437     assertFalse(it.hasNext());
1438
1439     // [start,end] fully contains 1 region and start of last
1440     // - 2 regions returned
1441     it = h.getBoundedStartIterator(3, 7);
1442     assertTrue(it.hasNext());
1443     next = it.next();
1444     assertEquals(3, next);
1445     next = it.next();
1446     assertEquals(6, next);
1447     assertFalse(it.hasNext());
1448
1449     // [start,end] contains whole of last region
1450     // - 1 region returned
1451     it = h.getBoundedStartIterator(4, 20);
1452     assertTrue(it.hasNext());
1453     next = it.next();
1454     assertEquals(6, next);
1455     assertFalse(it.hasNext());
1456   }
1457
1458   @Test(groups = "Functional")
1459   public void testVisibleBlocksVisBoundsIterator()
1460   {
1461     HiddenColumns h = new HiddenColumns();
1462     Iterator<int[]> regions = h.getVisContigsIterator(0, 31, true);
1463
1464     // only 1 visible region spanning 0-30 if nothing is hidden
1465     assertTrue(regions.hasNext());
1466     int[] region = regions.next();
1467     assertEquals(0, region[0]);
1468     assertEquals(30, region[1]);
1469     assertFalse(regions.hasNext());
1470
1471     // hide 1 region in middle
1472     // 2 regions one on either side
1473     // second region boundary accounts for hidden columns
1474     h.hideColumns(10, 15);
1475     regions = h.getVisContigsIterator(0, 31, true);
1476
1477     assertTrue(regions.hasNext());
1478     region = regions.next();
1479     assertEquals(0, region[0]);
1480     assertEquals(9, region[1]);
1481     region = regions.next();
1482     assertEquals(16, region[0]);
1483     assertEquals(36, region[1]);
1484     assertFalse(regions.hasNext());
1485
1486     // single hidden region at left
1487     h = new HiddenColumns();
1488     h.hideColumns(0, 5);
1489     regions = h.getVisContigsIterator(0, 31, true);
1490
1491     assertTrue(regions.hasNext());
1492     region = regions.next();
1493     assertEquals(6, region[0]);
1494     assertEquals(36, region[1]);
1495     assertFalse(regions.hasNext());
1496
1497     // single hidden region at right
1498     h = new HiddenColumns();
1499     h.hideColumns(27, 30);
1500     regions = h.getVisContigsIterator(0, 31, true);
1501
1502     assertTrue(regions.hasNext());
1503     region = regions.next();
1504     assertEquals(0, region[0]);
1505     assertEquals(26, region[1]);
1506     region = regions.next();
1507     assertEquals(31, region[0]);
1508     assertEquals(34, region[1]);
1509     assertFalse(regions.hasNext());
1510
1511     // hidden region at left + hidden region in middle
1512     h = new HiddenColumns();
1513     h.hideColumns(0, 5);
1514     h.hideColumns(23, 25);
1515     regions = h.getVisContigsIterator(0, 31, true);
1516
1517     assertTrue(regions.hasNext());
1518     region = regions.next();
1519     assertEquals(6, region[0]);
1520     assertEquals(22, region[1]);
1521     region = regions.next();
1522     assertEquals(26, region[0]);
1523     assertEquals(39, region[1]);
1524     assertFalse(regions.hasNext());
1525
1526     // hidden region at right + hidden region in middle
1527     h = new HiddenColumns();
1528     h.hideColumns(27, 30);
1529     h.hideColumns(11, 14);
1530     regions = h.getVisContigsIterator(0, 31, true);
1531
1532     assertTrue(regions.hasNext());
1533     region = regions.next();
1534     assertEquals(0, region[0]);
1535     assertEquals(10, region[1]);
1536     region = regions.next();
1537     assertEquals(15, region[0]);
1538     assertEquals(26, region[1]);
1539     region = regions.next();
1540     assertEquals(31, region[0]);
1541     assertEquals(38, region[1]);
1542     assertFalse(regions.hasNext());
1543
1544     // hidden region at left and right
1545     h = new HiddenColumns();
1546     h.hideColumns(27, 35);
1547     h.hideColumns(0, 4);
1548     regions = h.getVisContigsIterator(0, 31, true);
1549
1550     assertTrue(regions.hasNext());
1551     region = regions.next();
1552     assertEquals(5, region[0]);
1553     assertEquals(26, region[1]);
1554     region = regions.next();
1555     assertEquals(36, region[0]);
1556     assertEquals(44, region[1]);
1557     assertFalse(regions.hasNext());
1558
1559     // multiple hidden regions
1560     h = new HiddenColumns();
1561     h.hideColumns(1, 1);
1562     h.hideColumns(3, 5);
1563     h.hideColumns(9, 11);
1564     h.hideColumns(22, 26);
1565
1566     regions = h.getVisContigsIterator(0, 31, true);
1567
1568     assertTrue(regions.hasNext());
1569     region = regions.next();
1570     assertEquals(0, region[0]);
1571     assertEquals(0, region[1]);
1572     region = regions.next();
1573     assertEquals(2, region[0]);
1574     assertEquals(2, region[1]);
1575     region = regions.next();
1576     assertEquals(6, region[0]);
1577     assertEquals(8, region[1]);
1578     region = regions.next();
1579     assertEquals(12, region[0]);
1580     assertEquals(21, region[1]);
1581     region = regions.next();
1582     assertEquals(27, region[0]);
1583     assertEquals(42, region[1]);
1584     assertFalse(regions.hasNext());
1585   }
1586
1587   /*
1588    * the VisibleColsIterator is tested elsewhere, this just tests that 
1589    * it can be retrieved from HiddenColumns
1590    */
1591   @Test(groups = "Functional")
1592   public void testGetVisibleColsIterator()
1593   {
1594     HiddenColumns h = new HiddenColumns();
1595     Iterator<Integer> it = h.getVisibleColsIterator(0, 10);
1596
1597     assertTrue(it instanceof VisibleColsIterator);
1598   }
1599
1600   @Test(groups = "Functional")
1601   public void testHashCode()
1602   {
1603     HiddenColumns h = new HiddenColumns();
1604     h.hideColumns(0, 25);
1605
1606     int result = h.hashCode();
1607     assertTrue(result > 0);
1608
1609     h.hideColumns(30, 50);
1610     assertTrue(h.hashCode() > 0);
1611     assertTrue(result != h.hashCode());
1612   }
1613 }