2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.datamodel;
23 import static org.testng.Assert.assertNull;
24 import static org.testng.AssertJUnit.assertEquals;
26 import jalview.analysis.AlignSeq;
27 import jalview.gui.JvOptionPane;
28 import jalview.io.AppletFormatAdapter;
29 import jalview.io.FileFormat;
31 import org.testng.Assert;
32 import org.testng.annotations.BeforeClass;
33 import org.testng.annotations.Test;
35 public class AlignmentAnnotationTests
38 @BeforeClass(alwaysRun = true)
39 public void setUpJvOptionPane()
41 JvOptionPane.setInteractiveMode(false);
42 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
45 @Test(groups = { "Functional" })
46 public void testCopyConstructor()
48 SequenceI sq = new Sequence("Foo", "ARAARARARAWEAWEAWRAWEAWE");
50 AlignmentAnnotation alc, alo = sq.getAnnotation()[0];
51 alc = new AlignmentAnnotation(alo);
53 // TODO: this only tests string equals (which is unreliable), should use
54 // refactored tests from StockholmFileTest
55 Assert.assertEquals(alc.toString(), alo.toString());
57 for (String key : alo.getProperties())
59 assertEquals("Property mismatch", alo.getProperty(key),
60 alc.getProperty(key));
65 * create some dummy annotation derived from the sequence
69 public static void createAnnotation(SequenceI sq)
71 Annotation[] al = new Annotation[sq.getLength()];
72 for (int i = 0; i < al.length; i++)
74 al[i] = new Annotation(new Annotation("" + sq.getCharAt(i), "",
75 (char) 0, sq.findPosition(i)));
77 AlignmentAnnotation alan = new AlignmentAnnotation(
78 "For " + sq.getName(), "Fake alignment annot", al);
79 // create a sequence mapping for the annotation vector in its current state
80 alan.createSequenceMapping(sq, sq.getStart(), false);
81 alan.setProperty("CreatedBy", "createAnnotation");
82 sq.addAlignmentAnnotation(alan);
86 * use this to test annotation derived from method above as it is transferred
87 * across different sequences derived from same dataset coordinate frame
91 public static void testAnnotTransfer(AlignmentAnnotation ala)
94 "Failed - need annotation created by createAnnotation method",
95 ala.description, "Fake alignment annot");
96 ala.adjustForAlignment();
97 for (int p = 0; p < ala.annotations.length; p++)
99 if (ala.annotations[p] != null)
102 "Mismatch at position " + p
103 + " between annotation position value and sequence"
104 + ala.annotations[p],
105 (int) ala.annotations[p].value,
106 ala.sequenceRef.findPosition(p));
112 * Tests the liftOver method and also exercises the functions for remapping
113 * annotation across different reference sequences. Here, the test is between
114 * different dataset frames (annotation transferred by mapping between
117 @Test(groups = { "Functional" })
118 public void testLiftOver()
120 SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
122 sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
123 SequenceI sqTo = new Sequence("toShort", "RCDEW");
125 sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
126 createAnnotation(sqTo);
127 AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
128 createAnnotation(sqFrom);
129 AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
130 AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo,
132 SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
133 alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
134 alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
135 alSeq1.setDatasetSequence(sqFrom);
136 SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
137 alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
138 alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
139 alSeq2.setDatasetSequence(sqTo);
140 System.out.println(new AppletFormatAdapter().formatSequences(
141 FileFormat.Stockholm, new Alignment(new SequenceI[]
142 { sqFrom, alSeq1, sqTo, alSeq2 }), true));
144 Mapping mp = align.getMappingFromS1(false);
146 AlignmentAnnotation almap1 = new AlignmentAnnotation(
147 sqTo.getAnnotation()[0]);
148 almap1.liftOver(sqFrom, mp);
149 assertEquals(almap1.sequenceRef, sqFrom);
150 alSeq1.addAlignmentAnnotation(almap1);
151 almap1.setSequenceRef(alSeq1);
152 almap1.adjustForAlignment();
153 AlignmentAnnotation almap2 = new AlignmentAnnotation(
154 sqFrom.getAnnotation()[0]);
155 almap2.liftOver(sqTo, mp);
156 assertEquals(almap2.sequenceRef, sqTo);
158 alSeq2.addAlignmentAnnotation(almap2);
159 almap2.setSequenceRef(alSeq2);
160 almap2.adjustForAlignment();
162 AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
163 all.addAnnotation(almap1);
164 all.addAnnotation(almap2);
165 System.out.println(new AppletFormatAdapter()
166 .formatSequences(FileFormat.Stockholm, all, true));
168 for (int p = 0; p < alSeq1.getLength(); p++)
170 Annotation orig1, trans1, orig2, trans2;
171 trans2 = almap2.annotations[p];
172 orig2 = origFrom.annotations[alSeq1.findPosition(p)
173 - sqFrom.getStart()];
174 orig1 = origTo.annotations[alSeq2.findPosition(p) - sqTo.getStart()];
175 trans1 = almap1.annotations[p];
176 if (trans1 == trans2)
178 System.out.println("Pos " + p + " mismatch");
182 "Mismatch on Original From and transferred annotation on 2",
183 (orig2 != null) ? orig2.toString() : null,
184 (trans2 != null) ? trans2.toString() : null);
186 "Mismatch on Original To and transferred annotation on 1",
187 (orig1 != null) ? orig1.toString() : null,
188 (trans1 != null) ? trans1.toString() : null);
189 String alm1 = "" + (almap1.annotations.length > p
190 ? almap1.annotations[p].displayCharacter
192 String alm2 = "" + (almap2.annotations.length > p
193 ? almap2.annotations[p].displayCharacter
195 assertEquals("Position " + p + " " + alm1 + " " + alm2, alm1, alm2);
199 @Test(groups = { "Functional" })
200 public void testAdjustForAlignment()
202 SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
203 seq.createDatasetSequence();
206 * Annotate positions 3/4/5 (CDE) with values 1/2/3
208 Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
209 new Annotation(2), new Annotation(3) };
210 AlignmentAnnotation ann = new AlignmentAnnotation("SS",
211 "secondary structure", anns);
212 seq.addAlignmentAnnotation(ann);
215 * Check annotation map before modifying aligned sequence
217 assertNull(ann.getAnnotationForPosition(1));
218 assertNull(ann.getAnnotationForPosition(2));
219 assertNull(ann.getAnnotationForPosition(6));
220 assertNull(ann.getAnnotationForPosition(7));
221 assertEquals(1, ann.getAnnotationForPosition(3).value, 0.001d);
222 assertEquals(2, ann.getAnnotationForPosition(4).value, 0.001d);
223 assertEquals(3, ann.getAnnotationForPosition(5).value, 0.001d);
226 * Trim the displayed sequence to BCD and adjust annotations
228 seq.setSequence("BCD");
231 ann.adjustForAlignment();
234 * Should now have annotations for aligned positions 2, 3Q (CD) only
236 assertEquals(3, ann.annotations.length);
237 assertNull(ann.annotations[0]);
238 assertEquals(1, ann.annotations[1].value, 0.001);
239 assertEquals(2, ann.annotations[2].value, 0.001);
243 * Test the method that defaults rna symbol to the one matching the preceding
244 * unmatched opening bracket (if any)
246 @Test(groups = { "Functional" })
247 public void testGetDefaultRnaHelixSymbol()
249 AlignmentAnnotation ann = new AlignmentAnnotation("SS",
250 "secondary structure", null);
251 assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
253 Annotation[] anns = new Annotation[20];
254 ann.annotations = anns;
255 assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
257 anns[1] = new Annotation("(", "S", '(', 0f);
258 assertEquals("(", ann.getDefaultRnaHelixSymbol(0));
259 assertEquals("(", ann.getDefaultRnaHelixSymbol(1));
260 assertEquals(")", ann.getDefaultRnaHelixSymbol(2));
261 assertEquals(")", ann.getDefaultRnaHelixSymbol(3));
266 anns[1] = new Annotation("(", "S", '(', 0f);
267 anns[3] = new Annotation("[", "S", '[', 0f);
268 anns[5] = new Annotation("{", "S", '{', 0f);
269 anns[7] = new Annotation("<", "S", '<', 0f);
270 anns[9] = new Annotation("}", "S", '}', 0f);
271 anns[11] = new Annotation(">", "S", '>', 0f);
272 anns[13] = new Annotation(")", "S", ')', 0f);
273 anns[15] = new Annotation("]", "S", ']', 0f);
275 String expected = "(())]]}}>>>>]]]](";
276 for (int i = 0; i < expected.length(); i++)
278 assertEquals("column " + i, String.valueOf(expected.charAt(i)),
279 ann.getDefaultRnaHelixSymbol(i));
283 * .(.[.(.).{.}.<.].D.
285 anns[1] = new Annotation("(", "S", '(', 0f);
286 anns[3] = new Annotation("[", "S", '[', 0f);
287 anns[5] = new Annotation("(", "S", '(', 0f);
288 anns[7] = new Annotation(")", "S", ')', 0f);
289 anns[9] = new Annotation("{", "S", '{', 0f);
290 anns[11] = new Annotation("}", "S", '}', 0f);
291 anns[13] = new Annotation("<", "S", '>', 0f);
292 anns[15] = new Annotation("]", "S", ']', 0f);
293 anns[17] = new Annotation("D", "S", 'D', 0f);
295 expected = "(())]]))]]}}]]>>>>dd";
296 for (int i = 0; i < expected.length(); i++)
298 assertEquals("column " + i, String.valueOf(expected.charAt(i)),
299 ann.getDefaultRnaHelixSymbol(i));
303 public static Annotation newAnnotation(String ann)
308 val = Float.parseFloat(ann);
309 } catch (NumberFormatException q)
313 return new Annotation(ann, ann, '\0', val);
316 @Test(groups = { "Functional" })
317 public void testIsQuantitative()
319 AlignmentAnnotation ann = null;
321 ann = new AlignmentAnnotation("an", "some an", null);
322 Assert.assertFalse(ann.isQuantitative(),
323 "Empty annotation set should not be quantitative.");
325 ann = new AlignmentAnnotation("an", "some an",
327 { newAnnotation("4"), newAnnotation("1"), newAnnotation("1"),
328 newAnnotation("0.1"), newAnnotation("0.3") });
329 Assert.assertTrue(ann.isQuantitative(),
330 "All numbers annotation set should be quantitative.");
332 ann = new AlignmentAnnotation("an", "some an",
334 { newAnnotation("E"), newAnnotation("E"), newAnnotation("E"),
335 newAnnotation("E"), newAnnotation("E") });
336 Assert.assertFalse(ann.isQuantitative(),
337 "All 'E' annotation set should not be quantitative.");
339 ann = new AlignmentAnnotation("an", "some an",
341 { newAnnotation("E"), newAnnotation("1"), newAnnotation("2"),
342 newAnnotation("3"), newAnnotation("E") });
343 Assert.assertTrue(ann.isQuantitative(),
344 "Mixed 'E' annotation set should be quantitative.");
347 @Test(groups = "Functional")
348 public void testMakeVisibleAnnotation()
350 HiddenColumns h = new HiddenColumns();
351 Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
352 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
353 new Annotation(5), new Annotation(6), new Annotation(7),
355 AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
359 AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann",
361 emptyann.makeVisibleAnnotation(h);
362 assertNull(emptyann.annotations);
364 emptyann.makeVisibleAnnotation(3, 4, h);
365 assertNull(emptyann.annotations);
367 // without bounds, does everything
368 ann.makeVisibleAnnotation(h);
369 assertEquals(12, ann.annotations.length);
370 assertNull(ann.annotations[0]);
371 assertNull(ann.annotations[1]);
372 assertEquals(1.0f, ann.annotations[2].value);
373 assertEquals(2.0f, ann.annotations[3].value);
374 assertEquals(3.0f, ann.annotations[4].value);
375 assertNull(ann.annotations[5]);
376 assertNull(ann.annotations[6]);
377 assertEquals(4.0f, ann.annotations[7].value);
378 assertEquals(5.0f, ann.annotations[8].value);
379 assertEquals(6.0f, ann.annotations[9].value);
380 assertEquals(7.0f, ann.annotations[10].value);
381 assertEquals(8.0f, ann.annotations[11].value);
383 // without hidden cols, just truncates
384 ann.makeVisibleAnnotation(3, 5, h);
385 assertEquals(3, ann.annotations.length);
386 assertEquals(2.0f, ann.annotations[0].value);
387 assertEquals(3.0f, ann.annotations[1].value);
388 assertNull(ann.annotations[2]);
390 anns = new Annotation[] { null, null, new Annotation(1),
391 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
392 new Annotation(5), new Annotation(6), new Annotation(7),
394 ann = new AlignmentAnnotation("an", "some an", anns);
396 ann.makeVisibleAnnotation(1, 9, h);
397 assertEquals(5, ann.annotations.length);
398 assertNull(ann.annotations[0]);
399 assertEquals(1.0f, ann.annotations[1].value);
400 assertEquals(2.0f, ann.annotations[2].value);
401 assertEquals(5.0f, ann.annotations[3].value);
402 assertEquals(6.0f, ann.annotations[4].value);
404 anns = new Annotation[] { null, null, new Annotation(1),
405 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
406 new Annotation(5), new Annotation(6), new Annotation(7),
408 ann = new AlignmentAnnotation("an", "some an", anns);
410 ann.makeVisibleAnnotation(1, 9, h);
411 assertEquals(3, ann.annotations.length);
412 assertEquals(2.0f, ann.annotations[0].value);
413 assertEquals(5.0f, ann.annotations[1].value);
414 assertEquals(6.0f, ann.annotations[2].value);
416 anns = new Annotation[] { null, null, new Annotation(1),
417 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
418 new Annotation(5), new Annotation(6), new Annotation(7),
419 new Annotation(8), new Annotation(9), new Annotation(10),
420 new Annotation(11), new Annotation(12), new Annotation(13),
421 new Annotation(14), new Annotation(15) };
422 ann = new AlignmentAnnotation("an", "some an", anns);
423 h = new HiddenColumns();
424 h.hideColumns(5, 18);
425 h.hideColumns(20, 21);
426 ann.makeVisibleAnnotation(1, 21, h);
427 assertEquals(5, ann.annotations.length);
428 assertEquals(1.0f, ann.annotations[1].value);
429 assertEquals(2.0f, ann.annotations[2].value);
430 assertEquals(3.0f, ann.annotations[3].value);
431 assertNull(ann.annotations[0]);
432 assertNull(ann.annotations[4]);