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