b4bab22e1b1d918cdea863140cbb6b483f9854c2
[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.findColumnPosition(5));
72
73     // hiding column 6 makes no difference
74     cs.hideColumns(6, 6);
75     assertEquals(5, cs.findColumnPosition(5));
76
77     // hiding column 4 moves column 5 to column 4
78     cs.hideColumns(4, 4);
79     assertEquals(4, cs.findColumnPosition(5));
80
81     // hiding column 4 moves column 4 to position 3
82     assertEquals(3, cs.findColumnPosition(4));
83
84     // hiding columns 1 and 2 moves column 5 to column 2
85     cs.hideColumns(1, 2);
86     assertEquals(2, cs.findColumnPosition(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.findColumnPosition(8));
97
98     // and moves column 24 to 13
99     assertEquals(13, cs2.findColumnPosition(24));
100
101     // and moves column 28 to 14
102     assertEquals(14, cs2.findColumnPosition(28));
103
104     // and moves column 40 to 25
105     assertEquals(25, cs2.findColumnPosition(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.findColumnPosition(2));
112
113     // check that column after the last hidden region doesn't crash
114     assertEquals(46, cs2.findColumnPosition(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.hideInsertionsFor(al.getSequenceAt(0));
424     assertEquals("G", ""
425             + al.getSequenceAt(0).getCharAt(cs.adjustForHiddenColumns(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   }
625
626   /**
627    * Test for the case when a hidden range encloses more one already hidden
628    * range
629    */
630   @Test(groups = { "Functional" })
631   public void testHideColumns_subsumingHidden()
632   {
633     /*
634      * JAL-2370 bug scenario:
635      * two hidden ranges subsumed by a third
636      */
637     HiddenColumns cs = new HiddenColumns();
638     cs.hideColumns(49, 59);
639     cs.hideColumns(69, 79);
640     Iterator<int[]> regions = cs.iterator();
641     assertEquals(2, cs.getNumberOfRegions());
642     assertEquals("[49, 59]", Arrays.toString(regions.next()));
643     assertEquals("[69, 79]", Arrays.toString(regions.next()));
644
645     cs.hideColumns(48, 80);
646     regions = cs.iterator();
647     assertEquals(1, cs.getNumberOfRegions());
648     assertEquals("[48, 80]", Arrays.toString(regions.next()));
649
650     /*
651      * another...joining hidden ranges
652      */
653     cs = new HiddenColumns();
654     cs.hideColumns(10, 20);
655     cs.hideColumns(30, 40);
656     cs.hideColumns(50, 60);
657     // hiding 21-49 should merge to one range
658     cs.hideColumns(21, 49);
659     regions = cs.iterator();
660     assertEquals(1, cs.getNumberOfRegions());
661     assertEquals("[10, 60]", Arrays.toString(regions.next()));
662
663     /*
664      * another...left overlap, subsumption, right overlap,
665      * no overlap of existing hidden ranges
666      */
667     cs = new HiddenColumns();
668     cs.hideColumns(10, 20);
669     cs.hideColumns(10, 20);
670     cs.hideColumns(30, 35);
671     cs.hideColumns(40, 50);
672     cs.hideColumns(60, 70);
673
674     cs.hideColumns(15, 45);
675     regions = cs.iterator();
676     assertEquals(2, cs.getNumberOfRegions());
677     assertEquals("[10, 50]", Arrays.toString(regions.next()));
678     assertEquals("[60, 70]", Arrays.toString(regions.next()));
679   }
680
681   @Test(groups = { "Functional" })
682   public void testHideBitset()
683   {
684     HiddenColumns cs;
685
686     BitSet one = new BitSet();
687
688     // one hidden range
689     one.set(1);
690     cs = new HiddenColumns();
691     cs.hideMarkedBits(one);
692     assertEquals(1, cs.getNumberOfRegions());
693
694     one.set(2);
695     cs = new HiddenColumns();
696     cs.hideMarkedBits(one);
697     assertEquals(1, cs.getNumberOfRegions());
698
699     one.set(3);
700     cs = new HiddenColumns();
701     cs.hideMarkedBits(one);
702     assertEquals(1, cs.getNumberOfRegions());
703
704     // split
705     one.clear(2);
706     cs = new HiddenColumns();
707     cs.hideMarkedBits(one);
708     assertEquals(2, cs.getNumberOfRegions());
709
710     assertEquals(0, cs.adjustForHiddenColumns(0));
711     assertEquals(2, cs.adjustForHiddenColumns(1));
712     assertEquals(4, cs.adjustForHiddenColumns(2));
713
714     // one again
715     one.clear(1);
716     cs = new HiddenColumns();
717     cs.hideMarkedBits(one);
718
719     assertEquals(1, cs.getNumberOfRegions());
720
721     assertEquals(0, cs.adjustForHiddenColumns(0));
722     assertEquals(1, cs.adjustForHiddenColumns(1));
723     assertEquals(2, cs.adjustForHiddenColumns(2));
724     assertEquals(4, cs.adjustForHiddenColumns(3));
725   }
726
727   @Test(groups = { "Functional" })
728   public void testMarkHiddenRegions()
729   {
730     BitSet toMark, fromMark;
731     long seed = -3241532;
732     Random number = new Random(seed);
733     for (int n = 0; n < 1000; n++)
734     {
735       // create a random bitfield
736       toMark = BitSet
737               .valueOf(new long[]
738       { number.nextLong(), number.nextLong(), number.nextLong() });
739       toMark.set(n * number.nextInt(10), n * (25 + number.nextInt(25)));
740       HiddenColumns hc = new HiddenColumns();
741
742       if (n == 0)
743       {
744         hc.markHiddenRegions(fromMark = new BitSet());
745         assertTrue(fromMark.isEmpty());
746       }
747
748       hc.hideMarkedBits(toMark);
749
750       // see if we can recover bitfield
751       hc.markHiddenRegions(fromMark = new BitSet());
752       assertEquals(toMark, fromMark);
753     }
754   }
755
756   @Test(groups = { "Functional" })
757   public void testRegionsToString()
758   {
759     HiddenColumns hc = new HiddenColumns();
760
761     String result = hc.regionsToString(",", "--");
762     assertEquals("", result);
763
764     hc.hideColumns(3, 7);
765     hc.hideColumns(10, 10);
766     hc.hideColumns(14, 15);
767
768     result = hc.regionsToString(",", "--");
769     assertEquals("3--7,10--10,14--15", result);
770   }
771
772   @Test(groups = "Functional")
773   public void testGetVisibleStartAndEndIndexTest()
774   {
775     Sequence seq = new Sequence("testSeq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
776     AlignmentI align = new Alignment(new SequenceI[] { seq });
777     HiddenColumns hc = new HiddenColumns();
778
779     int[] startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
780     assertEquals(0, startEnd[0]);
781     assertEquals(25, startEnd[1]);
782
783     hc.hideColumns(0, 0);
784     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
785     assertEquals(1, startEnd[0]);
786     assertEquals(25, startEnd[1]);
787
788     hc.hideColumns(6, 9);
789     hc.hideColumns(11, 12);
790     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
791     assertEquals(1, startEnd[0]);
792     assertEquals(25, startEnd[1]);
793
794     hc.hideColumns(24, 25);
795     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
796     System.out.println(startEnd[0] + " : " + startEnd[1]);
797     assertEquals(1, startEnd[0]);
798     assertEquals(23, startEnd[1]);
799
800     // force lowest range to start of alignment
801     hc = new HiddenColumns();
802     hc.hideColumns(3, 4);
803     startEnd = hc.getVisibleStartAndEndIndex(align.getWidth());
804     assertEquals(0, startEnd[0]);
805     assertEquals(25, startEnd[1]);
806   }
807
808   @Test(groups = "Functional")
809   public void testGetRegionWithEdgeAtRes()
810   {
811     HiddenColumns hc = new HiddenColumns();
812
813     int[] result = hc.getRegionWithEdgeAtRes(5);
814     assertNull(result);
815
816     hc.hideColumns(3, 7);
817     hc.hideColumns(10, 10);
818     hc.hideColumns(14, 15);
819
820     result = hc.getRegionWithEdgeAtRes(2);
821     assertEquals(3, result[0]);
822     assertEquals(7, result[1]);
823
824     result = hc.getRegionWithEdgeAtRes(4);
825     assertEquals(10, result[0]);
826     assertEquals(10, result[1]);
827
828     result = hc.getRegionWithEdgeAtRes(5);
829     assertEquals(10, result[0]);
830     assertEquals(10, result[1]);
831
832     result = hc.getRegionWithEdgeAtRes(6);
833     assertNull(result);
834
835     result = hc.getRegionWithEdgeAtRes(0);
836     assertNull(result);
837
838     result = hc.getRegionWithEdgeAtRes(7);
839     assertEquals(14, result[0]);
840     assertEquals(15, result[1]);
841
842     result = hc.getRegionWithEdgeAtRes(8);
843     assertEquals(14, result[0]);
844     assertEquals(15, result[1]);
845
846     result = hc.getRegionWithEdgeAtRes(16);
847     assertNull(result);
848   }
849
850   @Test(groups = "Functional")
851   public void testPropagateInsertions()
852   {
853     // create an alignment with no gaps - this will be the profile seq and other
854     // JPRED seqs
855     AlignmentGenerator gen = new AlignmentGenerator(false);
856     AlignmentI al = gen.generate(25, 10, 1234, 0, 0);
857
858     // get the profileseq
859     SequenceI profileseq = al.getSequenceAt(0);
860     SequenceI gappedseq = new Sequence(profileseq);
861     gappedseq.insertCharAt(5, al.getGapCharacter());
862     gappedseq.insertCharAt(6, al.getGapCharacter());
863     gappedseq.insertCharAt(7, al.getGapCharacter());
864     gappedseq.insertCharAt(8, al.getGapCharacter());
865
866     // force different kinds of padding
867     al.getSequenceAt(3).deleteChars(2, 23);
868     al.getSequenceAt(4).deleteChars(2, 27);
869     al.getSequenceAt(5).deleteChars(10, 27);
870
871     // create an alignment view with the gapped sequence
872     SequenceI[] seqs = new SequenceI[1];
873     seqs[0] = gappedseq;
874     AlignmentI newal = new Alignment(seqs);
875     HiddenColumns hidden = new HiddenColumns();
876     hidden.hideColumns(15, 17);
877
878     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
879             false);
880
881     // confirm that original contigs are as expected
882     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 25, false);
883     int[] region = visible.next();
884     assertEquals("[0, 14]", Arrays.toString(region));
885     region = visible.next();
886     assertEquals("[18, 24]", Arrays.toString(region));
887
888     // propagate insertions
889     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
890             view);
891
892     // confirm that the contigs have changed to account for the gaps
893     visible = result.getVisContigsIterator(0, 25, false);
894     region = visible.next();
895     assertEquals("[0, 10]", Arrays.toString(region));
896     region = visible.next();
897     assertEquals("[14, 24]", Arrays.toString(region));
898
899     // confirm the alignment has been changed so that the other sequences have
900     // gaps inserted where the columns are hidden
901     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[10]));
902     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[11]));
903     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[12]));
904     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[13]));
905     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[14]));
906
907   }
908
909   @Test(groups = "Functional")
910   public void testPropagateInsertionsOverlap()
911   {
912     // test propagateInsertions where gaps and hiddenColumns overlap
913
914     // create an alignment with no gaps - this will be the profile seq and other
915     // JPRED seqs
916     AlignmentGenerator gen = new AlignmentGenerator(false);
917     AlignmentI al = gen.generate(20, 10, 1234, 0, 0);
918
919     // get the profileseq
920     SequenceI profileseq = al.getSequenceAt(0);
921     SequenceI gappedseq = new Sequence(profileseq);
922     gappedseq.insertCharAt(5, al.getGapCharacter());
923     gappedseq.insertCharAt(6, al.getGapCharacter());
924     gappedseq.insertCharAt(7, al.getGapCharacter());
925     gappedseq.insertCharAt(8, al.getGapCharacter());
926
927     // create an alignment view with the gapped sequence
928     SequenceI[] seqs = new SequenceI[1];
929     seqs[0] = gappedseq;
930     AlignmentI newal = new Alignment(seqs);
931
932     // hide columns so that some overlap with the gaps
933     HiddenColumns hidden = new HiddenColumns();
934     hidden.hideColumns(7, 10);
935
936     AlignmentView view = new AlignmentView(newal, hidden, null, true, false,
937             false);
938
939     // confirm that original contigs are as expected
940     Iterator<int[]> visible = hidden.getVisContigsIterator(0, 20, false);
941     int[] region = visible.next();
942     assertEquals("[0, 6]", Arrays.toString(region));
943     region = visible.next();
944     assertEquals("[11, 19]", Arrays.toString(region));
945     assertFalse(visible.hasNext());
946
947     // propagate insertions
948     HiddenColumns result = HiddenColumns.propagateInsertions(profileseq, al,
949             view);
950
951     // confirm that the contigs have changed to account for the gaps
952     visible = result.getVisContigsIterator(0, 20, false);
953     region = visible.next();
954     assertEquals("[0, 4]", Arrays.toString(region));
955     region = visible.next();
956     assertEquals("[7, 19]", Arrays.toString(region));
957     assertFalse(visible.hasNext());
958
959     // confirm the alignment has been changed so that the other sequences have
960     // gaps inserted where the columns are hidden
961     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[4]));
962     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[5]));
963     assertTrue(Comparison.isGap(al.getSequenceAt(1).getSequence()[6]));
964     assertFalse(Comparison.isGap(al.getSequenceAt(1).getSequence()[7]));
965   }
966
967   @Test(groups = "Functional")
968   public void testHasHiddenColumns()
969   {
970     HiddenColumns h = new HiddenColumns();
971
972     // new HiddenColumns2 has no hidden cols
973     assertFalse(h.hasHiddenColumns());
974
975     // some columns hidden, returns true
976     h.hideColumns(5, 10);
977     assertTrue(h.hasHiddenColumns());
978
979     // reveal columns, no hidden cols again
980     ColumnSelection sel = new ColumnSelection();
981     h.revealAllHiddenColumns(sel);
982     assertFalse(h.hasHiddenColumns());
983   }
984
985   @Test(groups = "Functional")
986   public void testHasManyHiddenColumns()
987   {
988     HiddenColumns h = new HiddenColumns();
989
990     // new HiddenColumns2 has no hidden cols
991     assertFalse(h.hasManyHiddenColumns());
992
993     // one set of columns hidden, returns false
994     h.hideColumns(5, 10);
995     assertFalse(h.hasManyHiddenColumns());
996
997     // two sets hidden, returns true
998     h.hideColumns(15, 17);
999     assertTrue(h.hasManyHiddenColumns());
1000
1001     // back to one block, asserts false
1002     h.hideColumns(11, 14);
1003     assertFalse(h.hasManyHiddenColumns());
1004   }
1005
1006   @Test(groups = "Functional")
1007   public void testAdjustForHiddenColumns()
1008   {
1009     HiddenColumns h = new HiddenColumns();
1010     // returns input value when there are no hidden columns
1011     assertEquals(10, h.adjustForHiddenColumns(10));
1012
1013     h.hideColumns(20, 30);
1014     assertEquals(10, h.adjustForHiddenColumns(10));
1015     assertEquals(20 + 11, h.adjustForHiddenColumns(20));
1016     assertEquals(35 + 11, h.adjustForHiddenColumns(35));
1017
1018     h.hideColumns(5, 7);
1019     assertEquals(10 + 3, h.adjustForHiddenColumns(10));
1020     assertEquals(20 + 14, h.adjustForHiddenColumns(20));
1021     assertEquals(35 + 14, h.adjustForHiddenColumns(35));
1022
1023     ColumnSelection sel = new ColumnSelection();
1024     h.revealAllHiddenColumns(sel);
1025     h.hideColumns(0, 1);
1026     assertEquals(4, h.adjustForHiddenColumns(2));
1027   }
1028
1029   @Test(groups = "Functional")
1030   public void testGetHiddenBoundaryLeft()
1031   {
1032     HiddenColumns h = new HiddenColumns();
1033
1034     // returns same value if no hidden cols
1035     assertEquals(3, h.getHiddenBoundaryLeft(3));
1036
1037     h.hideColumns(5, 10);
1038     assertEquals(10, h.getHiddenBoundaryLeft(15));
1039     assertEquals(3, h.getHiddenBoundaryLeft(3));
1040     assertEquals(7, h.getHiddenBoundaryLeft(7));
1041
1042     h.hideColumns(15, 20);
1043     assertEquals(10, h.getHiddenBoundaryLeft(15));
1044     assertEquals(20, h.getHiddenBoundaryLeft(21));
1045   }
1046
1047   @Test(groups = "Functional")
1048   public void testGetHiddenBoundaryRight()
1049   {
1050     HiddenColumns h = new HiddenColumns();
1051
1052     // returns same value if no hidden cols
1053     assertEquals(3, h.getHiddenBoundaryRight(3));
1054
1055     h.hideColumns(5, 10);
1056     assertEquals(5, h.getHiddenBoundaryRight(3));
1057     assertEquals(15, h.getHiddenBoundaryRight(15));
1058     assertEquals(7, h.getHiddenBoundaryRight(7));
1059
1060     h.hideColumns(15, 20);
1061     assertEquals(15, h.getHiddenBoundaryRight(7));
1062     assertEquals(15, h.getHiddenBoundaryRight(14));
1063
1064     // returns same value if there is no next hidden column
1065     assertEquals(22, h.getHiddenBoundaryRight(22));
1066   }
1067
1068   @Test(groups = "Functional")
1069   public void testIterator()
1070   {
1071     HiddenColumns h = new HiddenColumns();
1072     Iterator<int[]> result = h.iterator();
1073     assertFalse(result.hasNext());
1074
1075     h.hideColumns(5, 10);
1076     result = h.iterator();
1077     int[] next = result.next();
1078     assertEquals(5, next[0]);
1079     assertEquals(10, next[1]);
1080     assertFalse(result.hasNext());
1081
1082     h.hideColumns(22, 23);
1083     result = h.iterator();
1084     next = result.next();
1085     assertEquals(5, next[0]);
1086     assertEquals(10, next[1]);
1087     next = result.next();
1088     assertEquals(22, next[0]);
1089     assertEquals(23, next[1]);
1090     assertFalse(result.hasNext());
1091
1092     // test for only one hidden region at start of alignment
1093     ColumnSelection sel = new ColumnSelection();
1094     h.revealAllHiddenColumns(sel);
1095     h.hideColumns(0, 1);
1096     result = h.iterator();
1097     next = result.next();
1098     assertEquals(0, next[0]);
1099     assertEquals(1, next[1]);
1100     assertFalse(result.hasNext());
1101   }
1102
1103   @Test(groups = "Functional")
1104   public void testGetVisibleSequenceStrings()
1105   {
1106     HiddenColumns h = new HiddenColumns();
1107     SequenceI seq1 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1108     SequenceI seq2 = new Sequence("TEST2", "VICYHRNDTGA");
1109     SequenceI[] seqs = new SequenceI[2];
1110     seqs[0] = seq1;
1111     seqs[1] = seq2;
1112     String[] result = h.getVisibleSequenceStrings(5, 10, seqs);
1113     assertEquals(2, result.length);
1114     assertEquals("WKQES", result[0]);
1115     assertEquals("RNDTG", result[1]);
1116
1117     h.hideColumns(6, 8);
1118     result = h.getVisibleSequenceStrings(5, 10, seqs);
1119     assertEquals(2, result.length);
1120     assertEquals("WS", result[0]);
1121     assertEquals("RG", result[1]);
1122
1123     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
1124     ColumnSelection sel = new ColumnSelection();
1125     h.revealAllHiddenColumns(sel);
1126     h.hideColumns(1, 3);
1127     h.hideColumns(6, 11);
1128     assertEquals("-D",
1129             h.getVisibleSequenceStrings(0, 5, new SequenceI[]
1130     { seq })[0]);
1131   }
1132
1133   @Test(groups = "Functional")
1134   public void testHideInsertionsFor()
1135   {
1136     HiddenColumns h = new HiddenColumns();
1137     HiddenColumns h2 = new HiddenColumns();
1138     SequenceI seq1 = new Sequence("TEST1", "GAL---MFW-KQESPVICY--HRNDT");
1139     SequenceI seq2 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1140
1141     h.hideInsertionsFor(seq2);
1142     assertTrue(h.equals(h2));
1143
1144     h.hideInsertionsFor(seq1);
1145     h2.hideColumns(3, 5);
1146     h2.hideColumns(9, 9);
1147     h2.hideColumns(19, 20);
1148     assertTrue(h.equals(h2));
1149   }
1150
1151   @Test(groups = "Functional")
1152   public void testHideMarkedBits()
1153   {
1154     HiddenColumns h = new HiddenColumns();
1155     HiddenColumns h2 = new HiddenColumns();
1156
1157     BitSet tohide = new BitSet(21);
1158     h.hideMarkedBits(tohide);
1159     assertTrue(h.equals(h2));
1160
1161     // NB in hideMarkedBits, the last bit is not set to hidden
1162     tohide.set(3, 6);
1163     tohide.set(9);
1164     tohide.set(19, 21);
1165     h.hideMarkedBits(tohide);
1166
1167     h2.hideColumns(3, 5);
1168     h2.hideColumns(9, 9);
1169     h2.hideColumns(19, 20);
1170     assertTrue(h.equals(h2));
1171   }
1172
1173   @Test(groups = "Functional")
1174   public void testMakeVisibleAnnotation()
1175   {
1176     HiddenColumns h = new HiddenColumns();
1177     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
1178         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1179         new Annotation(5), new Annotation(6), new Annotation(7),
1180         new Annotation(8) };
1181     AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
1182             anns);
1183
1184     // null annotation
1185     AlignmentAnnotation nullann = null;
1186     h.makeVisibleAnnotation(nullann);
1187     assertNull(nullann);
1188     
1189     h.makeVisibleAnnotation(1, 2, nullann);
1190     assertNull(nullann);
1191
1192     // null annotations
1193     AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann", null);
1194     h.makeVisibleAnnotation(emptyann);
1195     assertNull(emptyann.annotations);
1196     
1197     h.makeVisibleAnnotation(3, 4, emptyann);
1198     assertNull(emptyann.annotations);
1199
1200     // without bounds, does everything
1201     h.makeVisibleAnnotation(ann);
1202     assertEquals(12, ann.annotations.length);
1203     assertNull(ann.annotations[0]);
1204     assertNull(ann.annotations[1]);
1205     assertEquals(1.0f, ann.annotations[2].value);
1206     assertEquals(2.0f, ann.annotations[3].value);
1207     assertEquals(3.0f, ann.annotations[4].value);
1208     assertNull(ann.annotations[5]);
1209     assertNull(ann.annotations[6]);
1210     assertEquals(4.0f, ann.annotations[7].value);
1211     assertEquals(5.0f, ann.annotations[8].value);
1212     assertEquals(6.0f, ann.annotations[9].value);
1213     assertEquals(7.0f, ann.annotations[10].value);
1214     assertEquals(8.0f, ann.annotations[11].value);
1215
1216     // without hidden cols, just truncates
1217     h.makeVisibleAnnotation(3, 5, ann);
1218     assertEquals(3, ann.annotations.length);
1219     assertEquals(2.0f, ann.annotations[0].value);
1220     assertEquals(3.0f, ann.annotations[1].value);
1221     assertNull(ann.annotations[2]);
1222
1223     anns = new Annotation[] { null, null, new Annotation(1),
1224         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1225         new Annotation(5), new Annotation(6), new Annotation(7),
1226         new Annotation(8) };
1227     ann = new AlignmentAnnotation("an", "some an", anns);
1228     h.hideColumns(4, 7);
1229     h.makeVisibleAnnotation(1, 9, ann);
1230     assertEquals(5, ann.annotations.length);
1231     assertNull(ann.annotations[0]);
1232     assertEquals(1.0f, ann.annotations[1].value);
1233     assertEquals(2.0f, ann.annotations[2].value);
1234     assertEquals(5.0f, ann.annotations[3].value);
1235     assertEquals(6.0f, ann.annotations[4].value);
1236
1237     anns = new Annotation[] { null, null, new Annotation(1),
1238         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1239         new Annotation(5), new Annotation(6), new Annotation(7),
1240         new Annotation(8) };
1241     ann = new AlignmentAnnotation("an", "some an", anns);
1242     h.hideColumns(1, 2);
1243     h.makeVisibleAnnotation(1, 9, ann);
1244     assertEquals(3, ann.annotations.length);
1245     assertEquals(2.0f, ann.annotations[0].value);
1246     assertEquals(5.0f, ann.annotations[1].value);
1247     assertEquals(6.0f, ann.annotations[2].value);
1248
1249     anns = new Annotation[] { null, null, new Annotation(1),
1250         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1251         new Annotation(5), new Annotation(6), new Annotation(7),
1252         new Annotation(8), new Annotation(9), new Annotation(10),
1253         new Annotation(11), new Annotation(12), new Annotation(13),
1254         new Annotation(14), new Annotation(15) };
1255     ann = new AlignmentAnnotation("an", "some an", anns);
1256     h = new HiddenColumns();
1257     h.hideColumns(5, 18);
1258     h.hideColumns(20, 21);
1259     h.makeVisibleAnnotation(1, 21, ann);
1260     assertEquals(5, ann.annotations.length);
1261     assertEquals(1.0f, ann.annotations[1].value);
1262     assertEquals(2.0f, ann.annotations[2].value);
1263     assertEquals(3.0f, ann.annotations[3].value);
1264     assertNull(ann.annotations[0]);
1265     assertNull(ann.annotations[4]);
1266   }
1267
1268   @Test(groups = "Functional")
1269   public void testSubtractVisibleColumns()
1270   {
1271     HiddenColumns h = new HiddenColumns();
1272     int result = h.subtractVisibleColumns(1, 10);
1273     assertEquals(9, result);
1274
1275     h.hideColumns(7, 9);
1276     result = h.subtractVisibleColumns(4, 10);
1277     assertEquals(3, result);
1278
1279     h.hideColumns(14, 15);
1280     result = h.subtractVisibleColumns(4, 10);
1281     assertEquals(3, result);
1282
1283     result = h.subtractVisibleColumns(10, 17);
1284     assertEquals(2, result);
1285
1286     result = h.subtractVisibleColumns(1, 7);
1287     assertEquals(5, result);
1288
1289     result = h.subtractVisibleColumns(1, 8);
1290     assertEquals(5, result);
1291
1292     result = h.subtractVisibleColumns(3, 15);
1293     assertEquals(10, result);
1294
1295     ColumnSelection sel = new ColumnSelection();
1296     h.revealAllHiddenColumns(sel);
1297     h.hideColumns(0, 30);
1298     result = h.subtractVisibleColumns(31, 0);
1299     assertEquals(-31, result);
1300
1301     HiddenColumns cs = new HiddenColumns();
1302
1303     // test that without hidden columns, findColumnNToLeft returns
1304     // position n to left of provided position
1305     long pos = cs.subtractVisibleColumns(3, 10);
1306     assertEquals(7, pos);
1307
1308     // 0 returns same position
1309     pos = cs.subtractVisibleColumns(0, 10);
1310     assertEquals(10, pos);
1311
1312     // overflow to left returns negative number
1313     pos = cs.subtractVisibleColumns(3, 0);
1314     assertEquals(-3, pos);
1315
1316     // test that with hidden columns to left of result column
1317     // behaviour is the same as above
1318     cs.hideColumns(1, 3);
1319
1320     // position n to left of provided position
1321     pos = cs.subtractVisibleColumns(3, 10);
1322     assertEquals(7, pos);
1323
1324     // 0 returns same position
1325     pos = cs.subtractVisibleColumns(0, 10);
1326     assertEquals(10, pos);
1327
1328     // test with one set of hidden columns between start and required position
1329     cs.hideColumns(12, 15);
1330     pos = cs.subtractVisibleColumns(8, 17);
1331     assertEquals(5, pos);
1332
1333     // test with two sets of hidden columns between start and required position
1334     cs.hideColumns(20, 21);
1335     pos = cs.subtractVisibleColumns(8, 23);
1336     assertEquals(9, pos);
1337
1338     // repeat last 2 tests with no hidden columns to left of required position
1339     ColumnSelection colsel = new ColumnSelection();
1340     cs.revealAllHiddenColumns(colsel);
1341
1342     // test with one set of hidden columns between start and required position
1343     cs.hideColumns(12, 15);
1344     pos = cs.subtractVisibleColumns(8, 17);
1345     assertEquals(5, pos);
1346
1347     // test with two sets of hidden columns between start and required position
1348     cs.hideColumns(20, 21);
1349     pos = cs.subtractVisibleColumns(8, 23);
1350     assertEquals(9, pos);
1351
1352   }
1353
1354
1355   @Test(groups = "Functional")
1356   public void testBoundedIterator()
1357   {
1358     HiddenColumns h = new HiddenColumns();
1359     Iterator<int[]> it = h.getBoundedIterator(0, 10);
1360
1361     // no hidden columns = nothing to iterate over
1362     assertFalse(it.hasNext());
1363
1364     // [start,end] contains all hidden columns
1365     // all regions are returned
1366     h.hideColumns(3, 10);
1367     h.hideColumns(14, 16);
1368     it = h.getBoundedIterator(0, 20);
1369     assertTrue(it.hasNext());
1370     int[] next = it.next();
1371     assertEquals(3, next[0]);
1372     assertEquals(10, next[1]);
1373     next = it.next();
1374     assertEquals(14, next[0]);
1375     assertEquals(16, next[1]);
1376     assertFalse(it.hasNext());
1377
1378     // [start,end] overlaps a region
1379     // 1 region returned
1380     it = h.getBoundedIterator(5, 7);
1381     assertTrue(it.hasNext());
1382     next = it.next();
1383     assertEquals(3, next[0]);
1384     assertEquals(10, next[1]);
1385     assertFalse(it.hasNext());
1386
1387     // [start,end] fully contains 1 region and start of last
1388     // - 2 regions returned
1389     it = h.getBoundedIterator(3, 15);
1390     assertTrue(it.hasNext());
1391     next = it.next();
1392     assertEquals(3, next[0]);
1393     assertEquals(10, next[1]);
1394     next = it.next();
1395     assertEquals(14, next[0]);
1396     assertEquals(16, next[1]);
1397     assertFalse(it.hasNext());
1398
1399     // [start,end] contains end of first region and whole of last region
1400     // - 2 regions returned
1401     it = h.getBoundedIterator(4, 20);
1402     assertTrue(it.hasNext());
1403     next = it.next();
1404     assertEquals(3, next[0]);
1405     assertEquals(10, next[1]);
1406     next = it.next();
1407     assertEquals(14, next[0]);
1408     assertEquals(16, next[1]);
1409     assertFalse(it.hasNext());
1410   }
1411
1412   @Test(groups = "Functional")
1413   public void testBoundedStartIterator()
1414   {
1415     HiddenColumns h = new HiddenColumns();
1416     Iterator<Integer> it = h.getBoundedStartIterator(0, 10);
1417
1418     // no hidden columns = nothing to iterate over
1419     assertFalse(it.hasNext());
1420
1421     // [start,end] contains all hidden columns
1422     // all regions are returned
1423     h.hideColumns(3, 10);
1424     h.hideColumns(14, 16);
1425     it = h.getBoundedStartIterator(0, 20);
1426     assertTrue(it.hasNext());
1427     int next = it.next();
1428     assertEquals(3, next);
1429     next = it.next();
1430     assertEquals(6, next);
1431     assertFalse(it.hasNext());
1432
1433     // [start,end] does not contain a start of a region
1434     // no regions to iterate over
1435     it = h.getBoundedStartIterator(4, 5);
1436     assertFalse(it.hasNext());
1437
1438     // [start,end] fully contains 1 region and start of last
1439     // - 2 regions returned
1440     it = h.getBoundedStartIterator(3, 7);
1441     assertTrue(it.hasNext());
1442     next = it.next();
1443     assertEquals(3, next);
1444     next = it.next();
1445     assertEquals(6, next);
1446     assertFalse(it.hasNext());
1447
1448     // [start,end] contains whole of last region
1449     // - 1 region returned
1450     it = h.getBoundedStartIterator(4, 20);
1451     assertTrue(it.hasNext());
1452     next = it.next();
1453     assertEquals(6, next);
1454     assertFalse(it.hasNext());
1455   }
1456
1457   @Test(groups = "Functional")
1458   public void testVisibleBlocksVisBoundsIterator()
1459   {
1460     HiddenColumns h = new HiddenColumns();
1461     Iterator<int[]> regions = h.getVisContigsIterator(0, 31, true);
1462
1463     // only 1 visible region spanning 0-30 if nothing is hidden
1464     assertTrue(regions.hasNext());
1465     int[] region = regions.next();
1466     assertEquals(0, region[0]);
1467     assertEquals(30, region[1]);
1468     assertFalse(regions.hasNext());
1469
1470     // hide 1 region in middle
1471     // 2 regions one on either side
1472     // second region boundary accounts for hidden columns
1473     h.hideColumns(10, 15);
1474     regions = h.getVisContigsIterator(0, 31, true);
1475
1476     assertTrue(regions.hasNext());
1477     region = regions.next();
1478     assertEquals(0, region[0]);
1479     assertEquals(9, region[1]);
1480     region = regions.next();
1481     assertEquals(16, region[0]);
1482     assertEquals(36, region[1]);
1483     assertFalse(regions.hasNext());
1484
1485     // single hidden region at left
1486     h = new HiddenColumns();
1487     h.hideColumns(0, 5);
1488     regions = h.getVisContigsIterator(0, 31, true);
1489
1490     assertTrue(regions.hasNext());
1491     region = regions.next();
1492     assertEquals(6, region[0]);
1493     assertEquals(36, region[1]);
1494     assertFalse(regions.hasNext());
1495
1496     // single hidden region at right
1497     h = new HiddenColumns();
1498     h.hideColumns(27, 30);
1499     regions = h.getVisContigsIterator(0, 31, true);
1500
1501     assertTrue(regions.hasNext());
1502     region = regions.next();
1503     assertEquals(0, region[0]);
1504     assertEquals(26, region[1]);
1505     region = regions.next();
1506     assertEquals(31, region[0]);
1507     assertEquals(34, region[1]);
1508     assertFalse(regions.hasNext());
1509
1510     // hidden region at left + hidden region in middle
1511     h = new HiddenColumns();
1512     h.hideColumns(0, 5);
1513     h.hideColumns(23, 25);
1514     regions = h.getVisContigsIterator(0, 31, true);
1515
1516     assertTrue(regions.hasNext());
1517     region = regions.next();
1518     assertEquals(6, region[0]);
1519     assertEquals(22, region[1]);
1520     region = regions.next();
1521     assertEquals(26, region[0]);
1522     assertEquals(39, region[1]);
1523     assertFalse(regions.hasNext());
1524
1525     // hidden region at right + hidden region in middle
1526     h = new HiddenColumns();
1527     h.hideColumns(27, 30);
1528     h.hideColumns(11, 14);
1529     regions = h.getVisContigsIterator(0, 31, true);
1530
1531     assertTrue(regions.hasNext());
1532     region = regions.next();
1533     assertEquals(0, region[0]);
1534     assertEquals(10, region[1]);
1535     region = regions.next();
1536     assertEquals(15, region[0]);
1537     assertEquals(26, region[1]);
1538     region = regions.next();
1539     assertEquals(31, region[0]);
1540     assertEquals(38, region[1]);
1541     assertFalse(regions.hasNext());
1542
1543     // hidden region at left and right
1544     h = new HiddenColumns();
1545     h.hideColumns(27, 35);
1546     h.hideColumns(0, 4);
1547     regions = h.getVisContigsIterator(0, 31, true);
1548
1549     assertTrue(regions.hasNext());
1550     region = regions.next();
1551     assertEquals(5, region[0]);
1552     assertEquals(26, region[1]);
1553     region = regions.next();
1554     assertEquals(36, region[0]);
1555     assertEquals(44, region[1]);
1556     assertFalse(regions.hasNext());
1557
1558     // multiple hidden regions
1559     h = new HiddenColumns();
1560     h.hideColumns(1, 1);
1561     h.hideColumns(3, 5);
1562     h.hideColumns(9, 11);
1563     h.hideColumns(22, 26);
1564
1565     regions = h.getVisContigsIterator(0, 31, true);
1566
1567     assertTrue(regions.hasNext());
1568     region = regions.next();
1569     assertEquals(0, region[0]);
1570     assertEquals(0, region[1]);
1571     region = regions.next();
1572     assertEquals(2, region[0]);
1573     assertEquals(2, region[1]);
1574     region = regions.next();
1575     assertEquals(6, region[0]);
1576     assertEquals(8, region[1]);
1577     region = regions.next();
1578     assertEquals(12, region[0]);
1579     assertEquals(21, region[1]);
1580     region = regions.next();
1581     assertEquals(27, region[0]);
1582     assertEquals(42, region[1]);
1583     assertFalse(regions.hasNext());
1584   }
1585
1586   /*
1587    * the VisibleColsIterator is tested elsewhere, this just tests that 
1588    * it can be retrieved from HiddenColumns
1589    */
1590   @Test(groups = "Functional")
1591   public void testGetVisibleColsIterator()
1592   {
1593     HiddenColumns h = new HiddenColumns();
1594     Iterator<Integer> it = h.getVisibleColsIterator(0, 10);
1595
1596     assertTrue(it instanceof VisibleColsIterator);
1597   }
1598
1599   @Test(groups = "Functional")
1600   public void testHashCode()
1601   {
1602     HiddenColumns h = new HiddenColumns();
1603     h.hideColumns(0, 25);
1604
1605     int result = h.hashCode();
1606     assertTrue(result > 0);
1607
1608     h.hideColumns(30, 50);
1609     assertTrue(h.hashCode() > 0);
1610     assertTrue(result != h.hashCode());
1611   }
1612 }