5d57ed20380c7a2f28d216ca1e976a461970dcfd
[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
1065   @Test(groups = "Functional")
1066   public void testIterator()
1067   {
1068     HiddenColumns h = new HiddenColumns();
1069     Iterator<int[]> result = h.iterator();
1070     assertFalse(result.hasNext());
1071
1072     h.hideColumns(5, 10);
1073     result = h.iterator();
1074     int[] next = result.next();
1075     assertEquals(5, next[0]);
1076     assertEquals(10, next[1]);
1077     assertFalse(result.hasNext());
1078
1079     h.hideColumns(22, 23);
1080     result = h.iterator();
1081     next = result.next();
1082     assertEquals(5, next[0]);
1083     assertEquals(10, next[1]);
1084     next = result.next();
1085     assertEquals(22, next[0]);
1086     assertEquals(23, next[1]);
1087     assertFalse(result.hasNext());
1088
1089     // test for only one hidden region at start of alignment
1090     ColumnSelection sel = new ColumnSelection();
1091     h.revealAllHiddenColumns(sel);
1092     h.hideColumns(0, 1);
1093     result = h.iterator();
1094     next = result.next();
1095     assertEquals(0, next[0]);
1096     assertEquals(1, next[1]);
1097     assertFalse(result.hasNext());
1098   }
1099
1100   @Test(groups = "Functional")
1101   public void testGetVisibleSequenceStrings()
1102   {
1103     HiddenColumns h = new HiddenColumns();
1104     SequenceI seq1 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1105     SequenceI seq2 = new Sequence("TEST2", "VICYHRNDTGA");
1106     SequenceI[] seqs = new SequenceI[2];
1107     seqs[0] = seq1;
1108     seqs[1] = seq2;
1109     String[] result = h.getVisibleSequenceStrings(5, 10, seqs);
1110     assertEquals(2, result.length);
1111     assertEquals("WKQES", result[0]);
1112     assertEquals("RNDTG", result[1]);
1113
1114     h.hideColumns(6, 8);
1115     result = h.getVisibleSequenceStrings(5, 10, seqs);
1116     assertEquals(2, result.length);
1117     assertEquals("WS", result[0]);
1118     assertEquals("RG", result[1]);
1119
1120     SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
1121     ColumnSelection sel = new ColumnSelection();
1122     h.revealAllHiddenColumns(sel);
1123     h.hideColumns(1, 3);
1124     h.hideColumns(6, 11);
1125     assertEquals("-D",
1126             h.getVisibleSequenceStrings(0, 5, new SequenceI[]
1127     { seq })[0]);
1128   }
1129
1130   @Test(groups = "Functional")
1131   public void testHideInsertionsFor()
1132   {
1133     HiddenColumns h = new HiddenColumns();
1134     HiddenColumns h2 = new HiddenColumns();
1135     SequenceI seq1 = new Sequence("TEST1", "GAL---MFW-KQESPVICY--HRNDT");
1136     SequenceI seq2 = new Sequence("TEST1", "GALMFWKQESPVICYHRNDT");
1137
1138     h.hideInsertionsFor(seq2);
1139     assertTrue(h.equals(h2));
1140
1141     h.hideInsertionsFor(seq1);
1142     h2.hideColumns(3, 5);
1143     h2.hideColumns(9, 9);
1144     h2.hideColumns(19, 20);
1145     assertTrue(h.equals(h2));
1146   }
1147
1148   @Test(groups = "Functional")
1149   public void testHideMarkedBits()
1150   {
1151     HiddenColumns h = new HiddenColumns();
1152     HiddenColumns h2 = new HiddenColumns();
1153
1154     BitSet tohide = new BitSet(21);
1155     h.hideMarkedBits(tohide);
1156     assertTrue(h.equals(h2));
1157
1158     // NB in hideMarkedBits, the last bit is not set to hidden
1159     tohide.set(3, 6);
1160     tohide.set(9);
1161     tohide.set(19, 21);
1162     h.hideMarkedBits(tohide);
1163
1164     h2.hideColumns(3, 5);
1165     h2.hideColumns(9, 9);
1166     h2.hideColumns(19, 20);
1167     assertTrue(h.equals(h2));
1168   }
1169
1170   @Test(groups = "Functional")
1171   public void testMakeVisibleAnnotation()
1172   {
1173     HiddenColumns h = new HiddenColumns();
1174     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
1175         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1176         new Annotation(5), new Annotation(6), new Annotation(7),
1177         new Annotation(8) };
1178     AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
1179             anns);
1180
1181     // null annotation
1182     AlignmentAnnotation nullann = null;
1183     h.makeVisibleAnnotation(nullann);
1184     assertNull(nullann);
1185     
1186     h.makeVisibleAnnotation(1, 2, nullann);
1187     assertNull(nullann);
1188
1189     // null annotations
1190     AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann", null);
1191     h.makeVisibleAnnotation(emptyann);
1192     assertNull(emptyann.annotations);
1193     
1194     h.makeVisibleAnnotation(3, 4, emptyann);
1195     assertNull(emptyann.annotations);
1196
1197     // without bounds, does everything
1198     h.makeVisibleAnnotation(ann);
1199     assertEquals(12, ann.annotations.length);
1200     assertNull(ann.annotations[0]);
1201     assertNull(ann.annotations[1]);
1202     assertEquals(1.0f, ann.annotations[2].value);
1203     assertEquals(2.0f, ann.annotations[3].value);
1204     assertEquals(3.0f, ann.annotations[4].value);
1205     assertNull(ann.annotations[5]);
1206     assertNull(ann.annotations[6]);
1207     assertEquals(4.0f, ann.annotations[7].value);
1208     assertEquals(5.0f, ann.annotations[8].value);
1209     assertEquals(6.0f, ann.annotations[9].value);
1210     assertEquals(7.0f, ann.annotations[10].value);
1211     assertEquals(8.0f, ann.annotations[11].value);
1212
1213     // without hidden cols, just truncates
1214     h.makeVisibleAnnotation(3, 5, ann);
1215     assertEquals(3, ann.annotations.length);
1216     assertEquals(2.0f, ann.annotations[0].value);
1217     assertEquals(3.0f, ann.annotations[1].value);
1218     assertNull(ann.annotations[2]);
1219
1220     anns = new Annotation[] { null, null, new Annotation(1),
1221         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1222         new Annotation(5), new Annotation(6), new Annotation(7),
1223         new Annotation(8) };
1224     ann = new AlignmentAnnotation("an", "some an", anns);
1225     h.hideColumns(4, 7);
1226     h.makeVisibleAnnotation(1, 9, ann);
1227     assertEquals(5, ann.annotations.length);
1228     assertNull(ann.annotations[0]);
1229     assertEquals(1.0f, ann.annotations[1].value);
1230     assertEquals(2.0f, ann.annotations[2].value);
1231     assertEquals(5.0f, ann.annotations[3].value);
1232     assertEquals(6.0f, ann.annotations[4].value);
1233
1234     anns = new Annotation[] { null, null, new Annotation(1),
1235         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1236         new Annotation(5), new Annotation(6), new Annotation(7),
1237         new Annotation(8) };
1238     ann = new AlignmentAnnotation("an", "some an", anns);
1239     h.hideColumns(1, 2);
1240     h.makeVisibleAnnotation(1, 9, ann);
1241     assertEquals(3, ann.annotations.length);
1242     assertEquals(2.0f, ann.annotations[0].value);
1243     assertEquals(5.0f, ann.annotations[1].value);
1244     assertEquals(6.0f, ann.annotations[2].value);
1245
1246     anns = new Annotation[] { null, null, new Annotation(1),
1247         new Annotation(2), new Annotation(3), null, null, new Annotation(4),
1248         new Annotation(5), new Annotation(6), new Annotation(7),
1249         new Annotation(8), new Annotation(9), new Annotation(10),
1250         new Annotation(11), new Annotation(12), new Annotation(13),
1251         new Annotation(14), new Annotation(15) };
1252     ann = new AlignmentAnnotation("an", "some an", anns);
1253     h = new HiddenColumns();
1254     h.hideColumns(5, 18);
1255     h.hideColumns(20, 21);
1256     h.makeVisibleAnnotation(1, 21, ann);
1257     assertEquals(5, ann.annotations.length);
1258     assertEquals(1.0f, ann.annotations[1].value);
1259     assertEquals(2.0f, ann.annotations[2].value);
1260     assertEquals(3.0f, ann.annotations[3].value);
1261     assertNull(ann.annotations[0]);
1262     assertNull(ann.annotations[4]);
1263   }
1264
1265   @Test(groups = "Functional")
1266   public void testSubtractVisibleColumns()
1267   {
1268     HiddenColumns h = new HiddenColumns();
1269     int result = h.subtractVisibleColumns(1, 10);
1270     assertEquals(9, result);
1271
1272     h.hideColumns(7, 9);
1273     result = h.subtractVisibleColumns(4, 10);
1274     assertEquals(3, result);
1275
1276     h.hideColumns(14, 15);
1277     result = h.subtractVisibleColumns(4, 10);
1278     assertEquals(3, result);
1279
1280     result = h.subtractVisibleColumns(10, 17);
1281     assertEquals(2, result);
1282
1283     result = h.subtractVisibleColumns(1, 7);
1284     assertEquals(5, result);
1285
1286     result = h.subtractVisibleColumns(1, 8);
1287     assertEquals(5, result);
1288
1289     result = h.subtractVisibleColumns(3, 15);
1290     assertEquals(10, result);
1291
1292     ColumnSelection sel = new ColumnSelection();
1293     h.revealAllHiddenColumns(sel);
1294     h.hideColumns(0, 30);
1295     result = h.subtractVisibleColumns(31, 0);
1296     assertEquals(-31, result);
1297
1298     HiddenColumns cs = new HiddenColumns();
1299
1300     // test that without hidden columns, findColumnNToLeft returns
1301     // position n to left of provided position
1302     long pos = cs.subtractVisibleColumns(3, 10);
1303     assertEquals(7, pos);
1304
1305     // 0 returns same position
1306     pos = cs.subtractVisibleColumns(0, 10);
1307     assertEquals(10, pos);
1308
1309     // overflow to left returns negative number
1310     pos = cs.subtractVisibleColumns(3, 0);
1311     assertEquals(-3, pos);
1312
1313     // test that with hidden columns to left of result column
1314     // behaviour is the same as above
1315     cs.hideColumns(1, 3);
1316
1317     // position n to left of provided position
1318     pos = cs.subtractVisibleColumns(3, 10);
1319     assertEquals(7, pos);
1320
1321     // 0 returns same position
1322     pos = cs.subtractVisibleColumns(0, 10);
1323     assertEquals(10, pos);
1324
1325     // test with one set of hidden columns between start and required position
1326     cs.hideColumns(12, 15);
1327     pos = cs.subtractVisibleColumns(8, 17);
1328     assertEquals(5, pos);
1329
1330     // test with two sets of hidden columns between start and required position
1331     cs.hideColumns(20, 21);
1332     pos = cs.subtractVisibleColumns(8, 23);
1333     assertEquals(9, pos);
1334
1335     // repeat last 2 tests with no hidden columns to left of required position
1336     ColumnSelection colsel = new ColumnSelection();
1337     cs.revealAllHiddenColumns(colsel);
1338
1339     // test with one set of hidden columns between start and required position
1340     cs.hideColumns(12, 15);
1341     pos = cs.subtractVisibleColumns(8, 17);
1342     assertEquals(5, pos);
1343
1344     // test with two sets of hidden columns between start and required position
1345     cs.hideColumns(20, 21);
1346     pos = cs.subtractVisibleColumns(8, 23);
1347     assertEquals(9, pos);
1348
1349   }
1350
1351
1352   @Test(groups = "Functional")
1353   public void testBoundedIterator()
1354   {
1355     HiddenColumns h = new HiddenColumns();
1356     Iterator<int[]> it = h.getBoundedIterator(0, 10);
1357
1358     // no hidden columns = nothing to iterate over
1359     assertFalse(it.hasNext());
1360
1361     // [start,end] contains all hidden columns
1362     // all regions are returned
1363     h.hideColumns(3, 10);
1364     h.hideColumns(14, 16);
1365     it = h.getBoundedIterator(0, 20);
1366     assertTrue(it.hasNext());
1367     int[] next = it.next();
1368     assertEquals(3, next[0]);
1369     assertEquals(10, next[1]);
1370     next = it.next();
1371     assertEquals(14, next[0]);
1372     assertEquals(16, next[1]);
1373     assertFalse(it.hasNext());
1374
1375     // [start,end] overlaps a region
1376     // 1 region returned
1377     it = h.getBoundedIterator(5, 7);
1378     assertTrue(it.hasNext());
1379     next = it.next();
1380     assertEquals(3, next[0]);
1381     assertEquals(10, next[1]);
1382     assertFalse(it.hasNext());
1383
1384     // [start,end] fully contains 1 region and start of last
1385     // - 2 regions returned
1386     it = h.getBoundedIterator(3, 15);
1387     assertTrue(it.hasNext());
1388     next = it.next();
1389     assertEquals(3, next[0]);
1390     assertEquals(10, next[1]);
1391     next = it.next();
1392     assertEquals(14, next[0]);
1393     assertEquals(16, next[1]);
1394     assertFalse(it.hasNext());
1395
1396     // [start,end] contains end of first region and whole of last region
1397     // - 2 regions returned
1398     it = h.getBoundedIterator(4, 20);
1399     assertTrue(it.hasNext());
1400     next = it.next();
1401     assertEquals(3, next[0]);
1402     assertEquals(10, next[1]);
1403     next = it.next();
1404     assertEquals(14, next[0]);
1405     assertEquals(16, next[1]);
1406     assertFalse(it.hasNext());
1407   }
1408
1409   @Test(groups = "Functional")
1410   public void testBoundedStartIterator()
1411   {
1412     HiddenColumns h = new HiddenColumns();
1413     Iterator<Integer> it = h.getBoundedStartIterator(0, 10);
1414
1415     // no hidden columns = nothing to iterate over
1416     assertFalse(it.hasNext());
1417
1418     // [start,end] contains all hidden columns
1419     // all regions are returned
1420     h.hideColumns(3, 10);
1421     h.hideColumns(14, 16);
1422     it = h.getBoundedStartIterator(0, 20);
1423     assertTrue(it.hasNext());
1424     int next = it.next();
1425     assertEquals(3, next);
1426     next = it.next();
1427     assertEquals(6, next);
1428     assertFalse(it.hasNext());
1429
1430     // [start,end] does not contain a start of a region
1431     // no regions to iterate over
1432     it = h.getBoundedStartIterator(4, 5);
1433     assertFalse(it.hasNext());
1434
1435     // [start,end] fully contains 1 region and start of last
1436     // - 2 regions returned
1437     it = h.getBoundedStartIterator(3, 7);
1438     assertTrue(it.hasNext());
1439     next = it.next();
1440     assertEquals(3, next);
1441     next = it.next();
1442     assertEquals(6, next);
1443     assertFalse(it.hasNext());
1444
1445     // [start,end] contains whole of last region
1446     // - 1 region returned
1447     it = h.getBoundedStartIterator(4, 20);
1448     assertTrue(it.hasNext());
1449     next = it.next();
1450     assertEquals(6, next);
1451     assertFalse(it.hasNext());
1452   }
1453
1454   @Test(groups = "Functional")
1455   public void testVisibleBlocksVisBoundsIterator()
1456   {
1457     HiddenColumns h = new HiddenColumns();
1458     Iterator<int[]> regions = h.getVisContigsIterator(0, 31, true);
1459
1460     // only 1 visible region spanning 0-30 if nothing is hidden
1461     assertTrue(regions.hasNext());
1462     int[] region = regions.next();
1463     assertEquals(0, region[0]);
1464     assertEquals(30, region[1]);
1465     assertFalse(regions.hasNext());
1466
1467     // hide 1 region in middle
1468     // 2 regions one on either side
1469     // second region boundary accounts for hidden columns
1470     h.hideColumns(10, 15);
1471     regions = h.getVisContigsIterator(0, 31, true);
1472
1473     assertTrue(regions.hasNext());
1474     region = regions.next();
1475     assertEquals(0, region[0]);
1476     assertEquals(9, region[1]);
1477     region = regions.next();
1478     assertEquals(16, region[0]);
1479     assertEquals(36, region[1]);
1480     assertFalse(regions.hasNext());
1481
1482     // single hidden region at left
1483     h = new HiddenColumns();
1484     h.hideColumns(0, 5);
1485     regions = h.getVisContigsIterator(0, 31, true);
1486
1487     assertTrue(regions.hasNext());
1488     region = regions.next();
1489     assertEquals(6, region[0]);
1490     assertEquals(36, region[1]);
1491     assertFalse(regions.hasNext());
1492
1493     // single hidden region at right
1494     h = new HiddenColumns();
1495     h.hideColumns(27, 30);
1496     regions = h.getVisContigsIterator(0, 31, true);
1497
1498     assertTrue(regions.hasNext());
1499     region = regions.next();
1500     assertEquals(0, region[0]);
1501     assertEquals(26, region[1]);
1502     region = regions.next();
1503     assertEquals(31, region[0]);
1504     assertEquals(34, region[1]);
1505     assertFalse(regions.hasNext());
1506
1507     // hidden region at left + hidden region in middle
1508     h = new HiddenColumns();
1509     h.hideColumns(0, 5);
1510     h.hideColumns(23, 25);
1511     regions = h.getVisContigsIterator(0, 31, true);
1512
1513     assertTrue(regions.hasNext());
1514     region = regions.next();
1515     assertEquals(6, region[0]);
1516     assertEquals(22, region[1]);
1517     region = regions.next();
1518     assertEquals(26, region[0]);
1519     assertEquals(39, region[1]);
1520     assertFalse(regions.hasNext());
1521
1522     // hidden region at right + hidden region in middle
1523     h = new HiddenColumns();
1524     h.hideColumns(27, 30);
1525     h.hideColumns(11, 14);
1526     regions = h.getVisContigsIterator(0, 31, true);
1527
1528     assertTrue(regions.hasNext());
1529     region = regions.next();
1530     assertEquals(0, region[0]);
1531     assertEquals(10, region[1]);
1532     region = regions.next();
1533     assertEquals(15, region[0]);
1534     assertEquals(26, region[1]);
1535     region = regions.next();
1536     assertEquals(31, region[0]);
1537     assertEquals(38, region[1]);
1538     assertFalse(regions.hasNext());
1539
1540     // hidden region at left and right
1541     h = new HiddenColumns();
1542     h.hideColumns(27, 35);
1543     h.hideColumns(0, 4);
1544     regions = h.getVisContigsIterator(0, 31, true);
1545
1546     assertTrue(regions.hasNext());
1547     region = regions.next();
1548     assertEquals(5, region[0]);
1549     assertEquals(26, region[1]);
1550     region = regions.next();
1551     assertEquals(36, region[0]);
1552     assertEquals(44, region[1]);
1553     assertFalse(regions.hasNext());
1554
1555     // multiple hidden regions
1556     h = new HiddenColumns();
1557     h.hideColumns(1, 1);
1558     h.hideColumns(3, 5);
1559     h.hideColumns(9, 11);
1560     h.hideColumns(22, 26);
1561
1562     regions = h.getVisContigsIterator(0, 31, true);
1563
1564     assertTrue(regions.hasNext());
1565     region = regions.next();
1566     assertEquals(0, region[0]);
1567     assertEquals(0, region[1]);
1568     region = regions.next();
1569     assertEquals(2, region[0]);
1570     assertEquals(2, region[1]);
1571     region = regions.next();
1572     assertEquals(6, region[0]);
1573     assertEquals(8, region[1]);
1574     region = regions.next();
1575     assertEquals(12, region[0]);
1576     assertEquals(21, region[1]);
1577     region = regions.next();
1578     assertEquals(27, region[0]);
1579     assertEquals(42, region[1]);
1580     assertFalse(regions.hasNext());
1581   }
1582
1583   /*
1584    * the VisibleColsIterator is tested elsewhere, this just tests that 
1585    * it can be retrieved from HiddenColumns
1586    */
1587   @Test(groups = "Functional")
1588   public void testGetVisibleColsIterator()
1589   {
1590     HiddenColumns h = new HiddenColumns();
1591     Iterator<Integer> it = h.getVisibleColsIterator(0, 10);
1592
1593     assertTrue(it instanceof VisibleColsIterator);
1594   }
1595
1596   @Test(groups = "Functional")
1597   public void testHashCode()
1598   {
1599     HiddenColumns h = new HiddenColumns();
1600     h.hideColumns(0, 25);
1601
1602     int result = h.hashCode();
1603     assertTrue(result > 0);
1604
1605     h.hideColumns(30, 50);
1606     assertTrue(h.hashCode() > 0);
1607     assertTrue(result != h.hashCode());
1608   }
1609 }