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.assertFalse;
24 import static org.testng.Assert.assertNull;
25 import static org.testng.Assert.assertTrue;
26 import static org.testng.AssertJUnit.assertEquals;
28 import jalview.analysis.AlignSeq;
29 import jalview.gui.JvOptionPane;
30 import jalview.io.AppletFormatAdapter;
31 import jalview.io.FileFormat;
33 import org.testng.Assert;
34 import org.testng.annotations.BeforeClass;
35 import org.testng.annotations.Test;
37 public class AlignmentAnnotationTests
40 @BeforeClass(alwaysRun = true)
41 public void setUpJvOptionPane()
43 JvOptionPane.setInteractiveMode(false);
44 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
47 @Test(groups = { "Functional" })
48 public void testCopyConstructor()
50 SequenceI sq = new Sequence("Foo", "ARAARARARAWEAWEAWRAWEAWE");
52 AlignmentAnnotation alc, alo = sq.getAnnotation()[0];
53 alc = new AlignmentAnnotation(alo);
54 for (String key : alo.getProperties())
56 assertEquals("Property mismatch", alo.getProperty(key),
57 alc.getProperty(key));
62 * create some dummy annotation derived from the sequence
66 public static void createAnnotation(SequenceI sq)
68 Annotation[] al = new Annotation[sq.getLength()];
69 for (int i = 0; i < al.length; i++)
71 al[i] = new Annotation(new Annotation("" + sq.getCharAt(i), "",
72 (char) 0, sq.findPosition(i)));
74 AlignmentAnnotation alan = new AlignmentAnnotation(
75 "For " + sq.getName(), "Fake alignment annot", al);
76 // create a sequence mapping for the annotation vector in its current state
77 alan.createSequenceMapping(sq, sq.getStart(), false);
78 alan.setProperty("CreatedBy", "createAnnotation");
79 sq.addAlignmentAnnotation(alan);
83 * use this to test annotation derived from method above as it is transferred
84 * across different sequences derived from same dataset coordinate frame
88 public static void testAnnotTransfer(AlignmentAnnotation ala)
91 "Failed - need annotation created by createAnnotation method",
92 ala.description, "Fake alignment annot");
93 ala.adjustForAlignment();
94 for (int p = 0; p < ala.annotations.length; p++)
96 if (ala.annotations[p] != null)
99 "Mismatch at position " + p
100 + " between annotation position value and sequence"
101 + ala.annotations[p],
102 (int) ala.annotations[p].value,
103 ala.sequenceRef.findPosition(p));
109 * Tests the liftOver method and also exercises the functions for remapping
110 * annotation across different reference sequences. Here, the test is between
111 * different dataset frames (annotation transferred by mapping between
114 @Test(groups = { "Functional" })
115 public void testLiftOver()
117 SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
119 sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
120 SequenceI sqTo = new Sequence("toShort", "RCDEW");
122 sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
123 createAnnotation(sqTo);
124 AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
125 createAnnotation(sqFrom);
126 AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
127 AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo,
129 SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
130 alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
131 alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
132 alSeq1.setDatasetSequence(sqFrom);
133 SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
134 alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
135 alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
136 alSeq2.setDatasetSequence(sqTo);
137 System.out.println(new AppletFormatAdapter().formatSequences(
138 FileFormat.Stockholm, new Alignment(new SequenceI[]
139 { sqFrom, alSeq1, sqTo, alSeq2 }), true));
141 Mapping mp = align.getMappingFromS1(false);
143 AlignmentAnnotation almap1 = new AlignmentAnnotation(
144 sqTo.getAnnotation()[0]);
145 almap1.liftOver(sqFrom, mp);
146 assertEquals(almap1.sequenceRef, sqFrom);
147 alSeq1.addAlignmentAnnotation(almap1);
148 almap1.setSequenceRef(alSeq1);
149 almap1.adjustForAlignment();
150 AlignmentAnnotation almap2 = new AlignmentAnnotation(
151 sqFrom.getAnnotation()[0]);
152 almap2.liftOver(sqTo, mp);
153 assertEquals(almap2.sequenceRef, sqTo);
155 alSeq2.addAlignmentAnnotation(almap2);
156 almap2.setSequenceRef(alSeq2);
157 almap2.adjustForAlignment();
159 AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
160 all.addAnnotation(almap1);
161 all.addAnnotation(almap2);
162 System.out.println(new AppletFormatAdapter()
163 .formatSequences(FileFormat.Stockholm, all, true));
165 for (int p = 0; p < alSeq1.getLength(); p++)
167 Annotation orig1, trans1, orig2, trans2;
168 trans2 = almap2.annotations[p];
169 orig2 = origFrom.annotations[alSeq1.findPosition(p)
170 - sqFrom.getStart()];
171 orig1 = origTo.annotations[alSeq2.findPosition(p) - sqTo.getStart()];
172 trans1 = almap1.annotations[p];
173 if (trans1 == trans2)
175 System.out.println("Pos " + p + " mismatch");
179 "Mismatch on Original From and transferred annotation on 2",
180 (orig2 != null) ? orig2.toString() : null,
181 (trans2 != null) ? trans2.toString() : null);
183 "Mismatch on Original To and transferred annotation on 1",
184 (orig1 != null) ? orig1.toString() : null,
185 (trans1 != null) ? trans1.toString() : null);
186 String alm1 = "" + (almap1.annotations.length > p
187 ? almap1.annotations[p].displayCharacter
189 String alm2 = "" + (almap2.annotations.length > p
190 ? almap2.annotations[p].displayCharacter
192 assertEquals("Position " + p + " " + alm1 + " " + alm2, alm1, alm2);
196 @Test(groups = { "Functional" })
197 public void testAdjustForAlignment()
199 SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
200 seq.createDatasetSequence();
203 * Annotate positions 3/4/5 (CDE) with values 1/2/3
205 Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
206 new Annotation(2), new Annotation(3) };
207 AlignmentAnnotation ann = new AlignmentAnnotation("SS",
208 "secondary structure", anns);
209 seq.addAlignmentAnnotation(ann);
212 * Check annotation map before modifying aligned sequence
214 assertNull(ann.getAnnotationForPosition(1));
215 assertNull(ann.getAnnotationForPosition(2));
216 assertNull(ann.getAnnotationForPosition(6));
217 assertNull(ann.getAnnotationForPosition(7));
218 assertEquals(1, ann.getAnnotationForPosition(3).value, 0.001d);
219 assertEquals(2, ann.getAnnotationForPosition(4).value, 0.001d);
220 assertEquals(3, ann.getAnnotationForPosition(5).value, 0.001d);
223 * Trim the displayed sequence to BCD and adjust annotations
225 seq.setSequence("BCD");
228 ann.adjustForAlignment();
231 * Should now have annotations for aligned positions 2, 3Q (CD) only
233 assertEquals(3, ann.annotations.length);
234 assertNull(ann.annotations[0]);
235 assertEquals(1, ann.annotations[1].value, 0.001);
236 assertEquals(2, ann.annotations[2].value, 0.001);
240 * Test the method that defaults rna symbol to the one matching the preceding
241 * unmatched opening bracket (if any)
243 @Test(groups = { "Functional" })
244 public void testGetDefaultRnaHelixSymbol()
246 AlignmentAnnotation ann = new AlignmentAnnotation("SS",
247 "secondary structure", null);
248 assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
250 Annotation[] anns = new Annotation[20];
251 ann.annotations = anns;
252 assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
254 anns[1] = new Annotation("(", "S", '(', 0f);
255 assertEquals("(", ann.getDefaultRnaHelixSymbol(0));
256 assertEquals("(", ann.getDefaultRnaHelixSymbol(1));
257 assertEquals(")", ann.getDefaultRnaHelixSymbol(2));
258 assertEquals(")", ann.getDefaultRnaHelixSymbol(3));
263 anns[1] = new Annotation("(", "S", '(', 0f);
264 anns[3] = new Annotation("[", "S", '[', 0f);
265 anns[5] = new Annotation("{", "S", '{', 0f);
266 anns[7] = new Annotation("<", "S", '<', 0f);
267 anns[9] = new Annotation("}", "S", '}', 0f);
268 anns[11] = new Annotation(">", "S", '>', 0f);
269 anns[13] = new Annotation(")", "S", ')', 0f);
270 anns[15] = new Annotation("]", "S", ']', 0f);
272 String expected = "(())]]}}>>>>]]]](";
273 for (int i = 0; i < expected.length(); i++)
275 assertEquals("column " + i, String.valueOf(expected.charAt(i)),
276 ann.getDefaultRnaHelixSymbol(i));
280 * .(.[.(.).{.}.<.].D.
282 anns[1] = new Annotation("(", "S", '(', 0f);
283 anns[3] = new Annotation("[", "S", '[', 0f);
284 anns[5] = new Annotation("(", "S", '(', 0f);
285 anns[7] = new Annotation(")", "S", ')', 0f);
286 anns[9] = new Annotation("{", "S", '{', 0f);
287 anns[11] = new Annotation("}", "S", '}', 0f);
288 anns[13] = new Annotation("<", "S", '>', 0f);
289 anns[15] = new Annotation("]", "S", ']', 0f);
290 anns[17] = new Annotation("D", "S", 'D', 0f);
292 expected = "(())]]))]]}}]]>>>>dd";
293 for (int i = 0; i < expected.length(); i++)
295 assertEquals("column " + i, String.valueOf(expected.charAt(i)),
296 ann.getDefaultRnaHelixSymbol(i));
300 public static Annotation newAnnotation(String ann)
305 val = Float.parseFloat(ann);
306 } catch (NumberFormatException q)
310 return new Annotation(ann, ann, '\0', val);
313 @Test(groups = { "Functional" })
314 public void testIsQuantitative()
316 AlignmentAnnotation ann = null;
318 ann = new AlignmentAnnotation("an", "some an", null);
319 Assert.assertFalse(ann.isQuantitative(),
320 "Empty annotation set should not be quantitative.");
322 ann = new AlignmentAnnotation("an", "some an",
324 { newAnnotation("4"), newAnnotation("1"), newAnnotation("1"),
325 newAnnotation("0.1"), newAnnotation("0.3") });
326 Assert.assertTrue(ann.isQuantitative(),
327 "All numbers annotation set should be quantitative.");
329 ann = new AlignmentAnnotation("an", "some an",
331 { newAnnotation("E"), newAnnotation("E"), newAnnotation("E"),
332 newAnnotation("E"), newAnnotation("E") });
333 Assert.assertFalse(ann.isQuantitative(),
334 "All 'E' annotation set should not be quantitative.");
336 ann = new AlignmentAnnotation("an", "some an",
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]);
433 * test the contact matrix nogroups property methods
435 @Test(groups = { "Functional" })
436 public void test_contactMatrixGroups()
438 AlignmentAnnotation aa = new AlignmentAnnotation("foo", "foo desc",
440 assertTrue(aa.isShowGroupsForContactMatrix());
441 aa.setShowGroupsForContactMatrix(false);
442 assertFalse(aa.isShowGroupsForContactMatrix());
443 AlignmentAnnotation copy = new AlignmentAnnotation(aa);
444 assertFalse(copy.isShowGroupsForContactMatrix());
445 aa.setShowGroupsForContactMatrix(true);
446 assertTrue(aa.isShowGroupsForContactMatrix());
447 // copy should not be updated
448 assertFalse(copy.isShowGroupsForContactMatrix());