JAL-4313 Test makeVisibleAnnotations
[jalview.git] / test / jalview / datamodel / AlignmentAnnotationTests.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 jalview.analysis.AlignSeq;
24 import jalview.gui.JvOptionPane;
25 import jalview.io.AppletFormatAdapter;
26 import jalview.io.FileFormat;
27 import org.testng.Assert;
28 import org.testng.annotations.BeforeClass;
29 import org.testng.annotations.Test;
30
31 import static jalview.datamodel.Annotation.EMPTY_ANNOTATION;
32 import static jalview.testutils.Matchers.matchesAnnotations;
33 import static org.hamcrest.MatcherAssert.assertThat;
34 import static org.hamcrest.Matchers.is;
35 import static org.hamcrest.Matchers.nullValue;
36 import static org.testng.Assert.assertNull;
37 import static org.testng.AssertJUnit.assertEquals;
38
39 public class AlignmentAnnotationTests
40 {
41
42   @BeforeClass(alwaysRun = true)
43   public void setUpJvOptionPane()
44   {
45     JvOptionPane.setInteractiveMode(false);
46     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
47   }
48
49   @Test(groups = { "Functional" })
50   public void testCopyConstructor()
51   {
52     SequenceI sq = new Sequence("Foo", "ARAARARARAWEAWEAWRAWEAWE");
53     createAnnotation(sq);
54     AlignmentAnnotation alc, alo = sq.getAnnotation()[0];
55     alc = new AlignmentAnnotation(alo);
56
57     // TODO: this only tests string equals (which is unreliable), should use
58     // refactored tests from StockholmFileTest
59     Assert.assertEquals(alc.toString(), alo.toString());
60
61     for (String key : alo.getProperties())
62     {
63       assertEquals("Property mismatch", alo.getProperty(key),
64           alc.getProperty(key));
65     }
66   }
67
68   /**
69    * create some dummy annotation derived from the sequence
70    * 
71    * @param sq
72    */
73   public static void createAnnotation(SequenceI sq)
74   {
75     Annotation[] al = new Annotation[sq.getLength()];
76     for (int i = 0; i < al.length; i++)
77     {
78       al[i] = new Annotation(new Annotation("" + sq.getCharAt(i), "", (char) 0,
79           sq.findPosition(i)));
80     }
81     AlignmentAnnotation alan = new AlignmentAnnotation("For " + sq.getName(),
82         "Fake alignment annot", al);
83     // create a sequence mapping for the annotation vector in its current state
84     alan.createSequenceMapping(sq, sq.getStart(), false);
85     alan.setProperty("CreatedBy", "createAnnotation");
86     sq.addAlignmentAnnotation(alan);
87   }
88
89   /**
90    * use this to test annotation derived from method above as it is transferred
91    * across different sequences derived from same dataset coordinate frame
92    * 
93    * @param ala
94    */
95   public static void testAnnotTransfer(AlignmentAnnotation ala)
96   {
97     assertEquals("Failed - need annotation created by createAnnotation method",
98         ala.description, "Fake alignment annot");
99     ala.adjustForAlignment();
100     for (int p = 0; p < ala.annotations.length; p++)
101     {
102       if (ala.annotations[p] != null)
103       {
104         assertEquals(
105             "Mismatch at position " + p
106                 + " between annotation position value and sequence"
107                 + ala.annotations[p],
108             (int) ala.annotations[p].value, ala.sequenceRef.findPosition(p));
109       }
110     }
111   }
112
113   /**
114    * Tests the liftOver method and also exercises the functions for remapping
115    * annotation across different reference sequences. Here, the test is between
116    * different dataset frames (annotation transferred by mapping between
117    * sequences)
118    */
119   @Test(groups = { "Functional" })
120   public void testLiftOver()
121   {
122     SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
123     sqFrom.setStart(10);
124     sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
125     SequenceI sqTo = new Sequence("toShort", "RCDEW");
126     sqTo.setStart(20);
127     sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
128     createAnnotation(sqTo);
129     AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
130     createAnnotation(sqFrom);
131     AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
132     AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo, AlignSeq.PEP);
133     SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
134     alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
135     alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
136     alSeq1.setDatasetSequence(sqFrom);
137     SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
138     alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
139     alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
140     alSeq2.setDatasetSequence(sqTo);
141     System.out
142         .println(new AppletFormatAdapter()
143             .formatSequences(FileFormat.Stockholm,
144                 new Alignment(new SequenceI[] { sqFrom, alSeq1, sqTo, alSeq2 }),
145                 true));
146
147     Mapping mp = align.getMappingFromS1(false);
148
149     AlignmentAnnotation almap1 = new AlignmentAnnotation(
150         sqTo.getAnnotation()[0]);
151     almap1.liftOver(sqFrom, mp);
152     assertEquals(almap1.sequenceRef, sqFrom);
153     alSeq1.addAlignmentAnnotation(almap1);
154     almap1.setSequenceRef(alSeq1);
155     almap1.adjustForAlignment();
156     AlignmentAnnotation almap2 = new AlignmentAnnotation(
157         sqFrom.getAnnotation()[0]);
158     almap2.liftOver(sqTo, mp);
159     assertEquals(almap2.sequenceRef, sqTo);
160
161     alSeq2.addAlignmentAnnotation(almap2);
162     almap2.setSequenceRef(alSeq2);
163     almap2.adjustForAlignment();
164
165     AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
166     all.addAnnotation(almap1);
167     all.addAnnotation(almap2);
168     System.out
169         .println(new AppletFormatAdapter()
170             .formatSequences(FileFormat.Stockholm, all, true));
171
172     for (int p = 0; p < alSeq1.getLength(); p++)
173     {
174       Annotation orig1, trans1, orig2, trans2;
175       trans2 = almap2.annotations[p];
176       orig2 = origFrom.annotations[alSeq1.findPosition(p) - sqFrom.getStart()];
177       orig1 = origTo.annotations[alSeq2.findPosition(p) - sqTo.getStart()];
178       trans1 = almap1.annotations[p];
179       if (trans1 == trans2)
180       {
181         System.out.println("Pos " + p + " mismatch");
182         continue;
183       }
184       assertEquals("Mismatch on Original From and transferred annotation on 2",
185           (orig2 != null) ? orig2.toString() : null,
186           (trans2 != null) ? trans2.toString() : null);
187       assertEquals("Mismatch on Original To and transferred annotation on 1",
188           (orig1 != null) ? orig1.toString() : null,
189           (trans1 != null) ? trans1.toString() : null);
190       String alm1 = "" + (almap1.annotations.length > p
191           ? almap1.annotations[p].displayCharacter
192           : "Out of range");
193       String alm2 = "" + (almap2.annotations.length > p
194           ? almap2.annotations[p].displayCharacter
195           : "Out of range");
196       assertEquals("Position " + p + " " + alm1 + " " + alm2, alm1, alm2);
197     }
198   }
199
200   @Test(groups = { "Functional" })
201   public void testAdjustForAlignment()
202   {
203     SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
204     seq.createDatasetSequence();
205
206     /*
207      * Annotate positions 3/4/5 (CDE) with values 1/2/3
208      */
209     Annotation[] anns = new Annotation[] {
210         null, null, new Annotation(1), new Annotation(2), new Annotation(3) };
211     AlignmentAnnotation ann = new AlignmentAnnotation("SS",
212         "secondary structure", anns);
213     seq.addAlignmentAnnotation(ann);
214
215     /*
216      * Check annotation map before modifying aligned sequence
217      */
218     assertNull(ann.getAnnotationForPosition(1));
219     assertNull(ann.getAnnotationForPosition(2));
220     assertNull(ann.getAnnotationForPosition(6));
221     assertNull(ann.getAnnotationForPosition(7));
222     assertEquals(1, ann.getAnnotationForPosition(3).value, 0.001d);
223     assertEquals(2, ann.getAnnotationForPosition(4).value, 0.001d);
224     assertEquals(3, ann.getAnnotationForPosition(5).value, 0.001d);
225
226     /*
227      * Trim the displayed sequence to BCD and adjust annotations
228      */
229     seq.setSequence("BCD");
230     seq.setStart(2);
231     seq.setEnd(4);
232     ann.adjustForAlignment();
233
234     /*
235      * Should now have annotations for aligned positions 2, 3Q (CD) only
236      */
237     assertEquals(3, ann.annotations.length);
238     assertNull(ann.annotations[0]);
239     assertEquals(1, ann.annotations[1].value, 0.001);
240     assertEquals(2, ann.annotations[2].value, 0.001);
241   }
242
243   /**
244    * Test the method that defaults rna symbol to the one matching the preceding
245    * unmatched opening bracket (if any)
246    */
247   @Test(groups = { "Functional" })
248   public void testGetDefaultRnaHelixSymbol()
249   {
250     AlignmentAnnotation ann = new AlignmentAnnotation("SS",
251         "secondary structure", null);
252     assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
253
254     Annotation[] anns = new Annotation[20];
255     ann.annotations = anns;
256     assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
257
258     anns[1] = new Annotation("(", "S", '(', 0f);
259     assertEquals("(", ann.getDefaultRnaHelixSymbol(0));
260     assertEquals("(", ann.getDefaultRnaHelixSymbol(1));
261     assertEquals(")", ann.getDefaultRnaHelixSymbol(2));
262     assertEquals(")", ann.getDefaultRnaHelixSymbol(3));
263
264     /*
265      * .(.[.{.<.}.>.).].
266      */
267     anns[1] = new Annotation("(", "S", '(', 0f);
268     anns[3] = new Annotation("[", "S", '[', 0f);
269     anns[5] = new Annotation("{", "S", '{', 0f);
270     anns[7] = new Annotation("<", "S", '<', 0f);
271     anns[9] = new Annotation("}", "S", '}', 0f);
272     anns[11] = new Annotation(">", "S", '>', 0f);
273     anns[13] = new Annotation(")", "S", ')', 0f);
274     anns[15] = new Annotation("]", "S", ']', 0f);
275
276     String expected = "(())]]}}>>>>]]]](";
277     for (int i = 0; i < expected.length(); i++)
278     {
279       assertEquals("column " + i, String.valueOf(expected.charAt(i)),
280           ann.getDefaultRnaHelixSymbol(i));
281     }
282
283     /*
284      * .(.[.(.).{.}.<.].D.
285      */
286     anns[1] = new Annotation("(", "S", '(', 0f);
287     anns[3] = new Annotation("[", "S", '[', 0f);
288     anns[5] = new Annotation("(", "S", '(', 0f);
289     anns[7] = new Annotation(")", "S", ')', 0f);
290     anns[9] = new Annotation("{", "S", '{', 0f);
291     anns[11] = new Annotation("}", "S", '}', 0f);
292     anns[13] = new Annotation("<", "S", '>', 0f);
293     anns[15] = new Annotation("]", "S", ']', 0f);
294     anns[17] = new Annotation("D", "S", 'D', 0f);
295
296     expected = "(())]]))]]}}]]>>>>dd";
297     for (int i = 0; i < expected.length(); i++)
298     {
299       assertEquals("column " + i, String.valueOf(expected.charAt(i)),
300           ann.getDefaultRnaHelixSymbol(i));
301     }
302   }
303
304   public static Annotation newAnnotation(String ann)
305   {
306     float val = 0f;
307     try
308     {
309       val = Float.parseFloat(ann);
310     } catch (NumberFormatException q)
311     {
312     }
313     ;
314     return new Annotation(ann, ann, '\0', val);
315   }
316
317   @Test(groups = { "Functional" })
318   public void testIsQuantitative()
319   {
320     AlignmentAnnotation ann = null;
321
322     ann = new AlignmentAnnotation("an", "some an", null);
323     Assert
324         .assertFalse(ann.isQuantitative(),
325             "Empty annotation set should not be quantitative.");
326
327     ann = new AlignmentAnnotation("an", "some an",
328         new Annotation[] {
329             newAnnotation("4"), newAnnotation("1"), newAnnotation("1"),
330             newAnnotation("0.1"), newAnnotation("0.3") });
331     Assert
332         .assertTrue(ann.isQuantitative(),
333             "All numbers annotation set should be quantitative.");
334
335     ann = new AlignmentAnnotation("an", "some an",
336         new Annotation[] {
337             newAnnotation("E"), newAnnotation("E"), newAnnotation("E"),
338             newAnnotation("E"), newAnnotation("E") });
339     Assert
340         .assertFalse(ann.isQuantitative(),
341             "All 'E' annotation set should not be quantitative.");
342
343     ann = new AlignmentAnnotation("an", "some an",
344         new Annotation[] {
345             newAnnotation("E"), newAnnotation("1"), newAnnotation("2"),
346             newAnnotation("3"), newAnnotation("E") });
347     Assert
348         .assertTrue(ann.isQuantitative(),
349             "Mixed 'E' annotation set should be quantitative.");
350   }
351
352   @Test(groups = "Functional")
353   public void testMakeVisibleAnnotation()
354   {
355     HiddenColumns h = new HiddenColumns();
356     Annotation[] anns = new Annotation[] {
357         null, null, new Annotation(1), new Annotation(2), new Annotation(3),
358         null, null, new Annotation(4), new Annotation(5), new Annotation(6),
359         new Annotation(7), new Annotation(8) };
360     AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an", anns);
361
362     // null annotations
363     AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann",
364         null);
365     emptyann.makeVisibleAnnotation(h);
366     assertNull(emptyann.annotations);
367
368     emptyann.makeVisibleAnnotation(3, 4, h);
369     assertNull(emptyann.annotations);
370
371     // without bounds, does everything
372     ann.makeVisibleAnnotation(h);
373     assertEquals(12, ann.annotations.length);
374     assertNull(ann.annotations[0]);
375     assertNull(ann.annotations[1]);
376     assertEquals(1.0f, ann.annotations[2].value);
377     assertEquals(2.0f, ann.annotations[3].value);
378     assertEquals(3.0f, ann.annotations[4].value);
379     assertNull(ann.annotations[5]);
380     assertNull(ann.annotations[6]);
381     assertEquals(4.0f, ann.annotations[7].value);
382     assertEquals(5.0f, ann.annotations[8].value);
383     assertEquals(6.0f, ann.annotations[9].value);
384     assertEquals(7.0f, ann.annotations[10].value);
385     assertEquals(8.0f, ann.annotations[11].value);
386
387     // without hidden cols, just truncates
388     ann.makeVisibleAnnotation(3, 5, h);
389     assertEquals(3, ann.annotations.length);
390     assertEquals(2.0f, ann.annotations[0].value);
391     assertEquals(3.0f, ann.annotations[1].value);
392     assertNull(ann.annotations[2]);
393
394     anns = new Annotation[] {
395         null, null, new Annotation(1), new Annotation(2), new Annotation(3),
396         null, null, new Annotation(4), new Annotation(5), new Annotation(6),
397         new Annotation(7), new Annotation(8) };
398     ann = new AlignmentAnnotation("an", "some an", anns);
399     h.hideColumns(4, 7);
400     ann.makeVisibleAnnotation(1, 9, h);
401     assertEquals(5, ann.annotations.length);
402     assertNull(ann.annotations[0]);
403     assertEquals(1.0f, ann.annotations[1].value);
404     assertEquals(2.0f, ann.annotations[2].value);
405     assertEquals(5.0f, ann.annotations[3].value);
406     assertEquals(6.0f, ann.annotations[4].value);
407
408     anns = new Annotation[] {
409         null, null, new Annotation(1), new Annotation(2), new Annotation(3),
410         null, null, new Annotation(4), new Annotation(5), new Annotation(6),
411         new Annotation(7), new Annotation(8) };
412     ann = new AlignmentAnnotation("an", "some an", anns);
413     h.hideColumns(1, 2);
414     ann.makeVisibleAnnotation(1, 9, h);
415     assertEquals(3, ann.annotations.length);
416     assertEquals(2.0f, ann.annotations[0].value);
417     assertEquals(5.0f, ann.annotations[1].value);
418     assertEquals(6.0f, ann.annotations[2].value);
419
420     anns = new Annotation[] {
421         null, null, new Annotation(1), new Annotation(2), new Annotation(3),
422         null, null, new Annotation(4), new Annotation(5), new Annotation(6),
423         new Annotation(7), new Annotation(8), new Annotation(9),
424         new Annotation(10), new Annotation(11), new Annotation(12),
425         new Annotation(13), new Annotation(14), new Annotation(15) };
426     ann = new AlignmentAnnotation("an", "some an", anns);
427     h = new HiddenColumns();
428     h.hideColumns(5, 18);
429     h.hideColumns(20, 21);
430     ann.makeVisibleAnnotation(1, 21, h);
431     assertEquals(5, ann.annotations.length);
432     assertEquals(1.0f, ann.annotations[1].value);
433     assertEquals(2.0f, ann.annotations[2].value);
434     assertEquals(3.0f, ann.annotations[3].value);
435     assertNull(ann.annotations[0]);
436     assertNull(ann.annotations[4]);
437   }
438
439   @Test(groups = "Functional")
440   public void testMakeVisibleAnnotation_NullAnnotationsAndNoColsHidden()
441   {
442     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", null);
443     HiddenColumns hc = new HiddenColumns();
444     ann.makeVisibleAnnotation(hc);
445     assertThat(ann.annotations, is(nullValue()));
446   }
447
448   @Test(groups = "Functional")
449   public void testMakeVisibleAnnotation_NullAnnotationsAndTrim()
450   {
451     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", null);
452     HiddenColumns hc = new HiddenColumns();
453     ann.makeVisibleAnnotation(3, 5, hc);
454     assertThat(ann.annotations, is(nullValue()));
455   }
456
457   @Test(groups = "Functional")
458   public void testMakeVisibleAnnotation_NoColsHidden()
459   {
460     Annotation[] annots = new Annotation[] {
461         EMPTY_ANNOTATION, EMPTY_ANNOTATION, new Annotation(1),
462         new Annotation(2), new Annotation(3), EMPTY_ANNOTATION,
463         EMPTY_ANNOTATION, new Annotation(4), new Annotation(5),
464         EMPTY_ANNOTATION, new Annotation(6), new Annotation(7),
465         new Annotation(8) };
466     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
467     HiddenColumns hc = new HiddenColumns();
468     ann.makeVisibleAnnotation(hc);
469     assertThat(ann.annotations, matchesAnnotations(annots));
470   }
471
472   @Test(groups = "Functional")
473   public void testMakeVisibleAnnotation_HideCols()
474   {
475     Annotation[] annots = new Annotation[] {
476         new Annotation(0), new Annotation(1), new Annotation(2),
477         new Annotation(3), new Annotation(4), new Annotation(5),
478         new Annotation(6), new Annotation(7), new Annotation(8) };
479     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
480     HiddenColumns hc = new HiddenColumns();
481     hc.hideColumns(2, 6);
482     ann.makeVisibleAnnotation(hc);
483     var expected = new Annotation[] {
484         new Annotation(0), new Annotation(1), new Annotation(7),
485         new Annotation(8) };
486     assertThat(ann.annotations, matchesAnnotations(expected));
487   }
488
489   @Test(groups = "Functional")
490   public void testMakeVisibleAnnotation_ExplicitFullWidthAndHideCols()
491   {
492     Annotation[] annots = new Annotation[] {
493         new Annotation(0), new Annotation(1), new Annotation(2),
494         new Annotation(3), new Annotation(4), new Annotation(5),
495         new Annotation(6), new Annotation(7), new Annotation(8),
496         new Annotation(9), new Annotation(10), new Annotation(11) };
497     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
498     HiddenColumns hc = new HiddenColumns();
499     hc.hideColumns(4, 7);
500     ann.makeVisibleAnnotation(0, 11, hc);
501     assertThat(ann.annotations,
502         matchesAnnotations(new Annotation(0), new Annotation(1),
503             new Annotation(2), new Annotation(3), new Annotation(8),
504             new Annotation(9), new Annotation(10), new Annotation(11)));
505   }
506
507   @Test(groups = "Functional")
508   public void testMakeVisibleAnnotation_ExplicitFullWidthAndHideCols2()
509   {
510     Annotation[] annots = new Annotation[] {
511         new Annotation(0), new Annotation(1), new Annotation(2),
512         new Annotation(3), new Annotation(4), new Annotation(5),
513         new Annotation(6), new Annotation(7), new Annotation(8), };
514     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
515     HiddenColumns hc = new HiddenColumns();
516     hc.hideColumns(4, 7);
517     ann.makeVisibleAnnotation(0, 8, hc);
518     assertThat(ann.annotations,
519         matchesAnnotations(new Annotation(0), new Annotation(1),
520             new Annotation(2), new Annotation(3), new Annotation(8)));
521   }
522
523   @Test(groups = "Functional")
524   public void testMakeVisibleAnnotation_HideColsWithEmptyAnnots()
525   {
526     Annotation[] annots = new Annotation[] {
527         EMPTY_ANNOTATION, EMPTY_ANNOTATION, new Annotation(1),
528         new Annotation(2), new Annotation(3), EMPTY_ANNOTATION,
529         EMPTY_ANNOTATION, new Annotation(4), new Annotation(5),
530         EMPTY_ANNOTATION, new Annotation(6), new Annotation(7),
531         new Annotation(8) };
532     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
533     HiddenColumns hc = new HiddenColumns();
534     hc.hideColumns(1, 3);
535     hc.hideColumns(8, 9);
536     ann.makeVisibleAnnotation(hc);
537     var expected = new Annotation[] {
538         EMPTY_ANNOTATION, new Annotation(3), EMPTY_ANNOTATION, EMPTY_ANNOTATION,
539         new Annotation(4), new Annotation(6), new Annotation(7),
540         new Annotation(8) };
541     assertThat(ann.annotations, matchesAnnotations(expected));
542   }
543
544   @Test(groups = "Functional")
545   public void testMakeVisibleAnnotation_HideColsWithNullAnnots()
546   {
547     Annotation[] annots = new Annotation[] {
548         null, null, new Annotation(2), null, new Annotation(4),
549         new Annotation(5), null, null };
550     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
551     HiddenColumns hc = new HiddenColumns();
552     hc.hideColumns(2, 4);
553     ann.makeVisibleAnnotation(hc);
554     var expected = new Annotation[] {
555         null, null, new Annotation(5), null, null };
556     assertThat(ann.annotations, matchesAnnotations(expected));
557   }
558
559   @Test(groups = "Functional")
560   public void testMakeVisibleAnnotation_Truncate()
561   {
562     Annotation[] annots = new Annotation[] {
563         new Annotation(0), new Annotation(1), new Annotation(2),
564         new Annotation(3), new Annotation(4), new Annotation(5),
565         new Annotation(6), new Annotation(7) };
566     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
567     ann.makeVisibleAnnotation(3, 6, new HiddenColumns());
568     assertThat(ann.annotations, matchesAnnotations(new Annotation(3),
569         new Annotation(4), new Annotation(5), new Annotation(6)));
570   }
571
572   @Test(groups = "Functional")
573   public void testMakeVisibleAnnotation_TruncateAndHideColumns()
574   {
575     Annotation[] annots = new Annotation[] {
576         new Annotation(0), new Annotation(1), new Annotation(2),
577         new Annotation(3), new Annotation(4), new Annotation(5),
578         new Annotation(6), new Annotation(7), new Annotation(8),
579         new Annotation(9), new Annotation(10), new Annotation(11) };
580     AlignmentAnnotation ann = new AlignmentAnnotation("label", "desc", annots);
581     HiddenColumns hc = new HiddenColumns();
582     hc.hideColumns(4, 7);
583     ann.makeVisibleAnnotation(1, 9, hc);
584     assertThat(ann.annotations,
585         matchesAnnotations(new Annotation(1), new Annotation(2),
586             new Annotation(3), new Annotation(8), new Annotation(9)));
587   }
588 }