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("For "
78 + 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)
101 assertEquals("Mismatch at position " + p
102 + " between annotation position value and sequence"
103 + ala.annotations[p], (int) ala.annotations[p].value,
104 ala.sequenceRef.findPosition(p));
110 * Tests the liftOver method and also exercises the functions for remapping
111 * annotation across different reference sequences. Here, the test is between
112 * different dataset frames (annotation transferred by mapping between
115 @Test(groups = { "Functional" })
116 public void testLiftOver()
118 SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
120 sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
121 SequenceI sqTo = new Sequence("toShort", "RCDEW");
123 sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
124 createAnnotation(sqTo);
125 AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
126 createAnnotation(sqFrom);
127 AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
128 AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo,
130 SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
131 alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
132 alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
133 alSeq1.setDatasetSequence(sqFrom);
134 SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
135 alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
136 alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
137 alSeq2.setDatasetSequence(sqTo);
138 System.out.println(new AppletFormatAdapter()
140 FileFormat.Stockholm, new Alignment(new SequenceI[] { sqFrom,
141 alSeq1, sqTo, alSeq2 }), true));
143 Mapping mp = align.getMappingFromS1(false);
145 AlignmentAnnotation almap1 = new AlignmentAnnotation(
146 sqTo.getAnnotation()[0]);
147 almap1.liftOver(sqFrom, mp);
148 assertEquals(almap1.sequenceRef, sqFrom);
149 alSeq1.addAlignmentAnnotation(almap1);
150 almap1.setSequenceRef(alSeq1);
151 almap1.adjustForAlignment();
152 AlignmentAnnotation almap2 = new AlignmentAnnotation(
153 sqFrom.getAnnotation()[0]);
154 almap2.liftOver(sqTo, mp);
155 assertEquals(almap2.sequenceRef, sqTo);
157 alSeq2.addAlignmentAnnotation(almap2);
158 almap2.setSequenceRef(alSeq2);
159 almap2.adjustForAlignment();
161 AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
162 all.addAnnotation(almap1);
163 all.addAnnotation(almap2);
164 System.out.println(new AppletFormatAdapter().formatSequences(
165 FileFormat.Stockholm,
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);
190 + (almap1.annotations.length > p ? almap1.annotations[p].displayCharacter
193 + (almap2.annotations.length > p ? 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", new Annotation[] {
326 newAnnotation("4"), newAnnotation("1"), newAnnotation("1"),
327 newAnnotation("0.1"), newAnnotation("0.3") });
328 Assert.assertTrue(ann.isQuantitative(),
329 "All numbers annotation set should be quantitative.");
331 ann = new AlignmentAnnotation("an", "some an", new Annotation[] {
332 newAnnotation("E"), newAnnotation("E"), newAnnotation("E"),
333 newAnnotation("E"), newAnnotation("E") });
334 Assert.assertFalse(ann.isQuantitative(),
335 "All 'E' annotation set should not be quantitative.");
337 ann = new AlignmentAnnotation("an", "some an", new Annotation[] {
338 newAnnotation("E"), newAnnotation("1"), newAnnotation("2"),
339 newAnnotation("3"), newAnnotation("E") });
340 Assert.assertTrue(ann.isQuantitative(),
341 "Mixed 'E' annotation set should be quantitative.");
344 @Test(groups = "Functional")
345 public void testMakeVisibleAnnotation()
347 HiddenColumns h = new HiddenColumns();
348 Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
349 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
350 new Annotation(5), new Annotation(6), new Annotation(7),
352 AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
356 AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann",
358 emptyann.makeVisibleAnnotation(h);
359 assertNull(emptyann.annotations);
361 emptyann.makeVisibleAnnotation(3, 4, h);
362 assertNull(emptyann.annotations);
364 // without bounds, does everything
365 ann.makeVisibleAnnotation(h);
366 assertEquals(12, ann.annotations.length);
367 assertNull(ann.annotations[0]);
368 assertNull(ann.annotations[1]);
369 assertEquals(1.0f, ann.annotations[2].value);
370 assertEquals(2.0f, ann.annotations[3].value);
371 assertEquals(3.0f, ann.annotations[4].value);
372 assertNull(ann.annotations[5]);
373 assertNull(ann.annotations[6]);
374 assertEquals(4.0f, ann.annotations[7].value);
375 assertEquals(5.0f, ann.annotations[8].value);
376 assertEquals(6.0f, ann.annotations[9].value);
377 assertEquals(7.0f, ann.annotations[10].value);
378 assertEquals(8.0f, ann.annotations[11].value);
380 // without hidden cols, just truncates
381 ann.makeVisibleAnnotation(3, 5, h);
382 assertEquals(3, ann.annotations.length);
383 assertEquals(2.0f, ann.annotations[0].value);
384 assertEquals(3.0f, ann.annotations[1].value);
385 assertNull(ann.annotations[2]);
387 anns = new Annotation[] { null, null, new Annotation(1),
388 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
389 new Annotation(5), new Annotation(6), new Annotation(7),
391 ann = new AlignmentAnnotation("an", "some an", anns);
393 ann.makeVisibleAnnotation(1, 9, h);
394 assertEquals(5, ann.annotations.length);
395 assertNull(ann.annotations[0]);
396 assertEquals(1.0f, ann.annotations[1].value);
397 assertEquals(2.0f, ann.annotations[2].value);
398 assertEquals(5.0f, ann.annotations[3].value);
399 assertEquals(6.0f, ann.annotations[4].value);
401 anns = new Annotation[] { null, null, new Annotation(1),
402 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
403 new Annotation(5), new Annotation(6), new Annotation(7),
405 ann = new AlignmentAnnotation("an", "some an", anns);
407 ann.makeVisibleAnnotation(1, 9, h);
408 assertEquals(3, ann.annotations.length);
409 assertEquals(2.0f, ann.annotations[0].value);
410 assertEquals(5.0f, ann.annotations[1].value);
411 assertEquals(6.0f, ann.annotations[2].value);
413 anns = new Annotation[] { null, null, new Annotation(1),
414 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
415 new Annotation(5), new Annotation(6), new Annotation(7),
416 new Annotation(8), new Annotation(9), new Annotation(10),
417 new Annotation(11), new Annotation(12), new Annotation(13),
418 new Annotation(14), new Annotation(15) };
419 ann = new AlignmentAnnotation("an", "some an", anns);
420 h = new HiddenColumns();
421 h.hideColumns(5, 18);
422 h.hideColumns(20, 21);
423 ann.makeVisibleAnnotation(1, 21, h);
424 assertEquals(5, ann.annotations.length);
425 assertEquals(1.0f, ann.annotations[1].value);
426 assertEquals(2.0f, ann.annotations[2].value);
427 assertEquals(3.0f, ann.annotations[3].value);
428 assertNull(ann.annotations[0]);
429 assertNull(ann.annotations[4]);