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);
52 for (String key : alo.getProperties())
54 assertEquals("Property mismatch", alo.getProperty(key),
55 alc.getProperty(key));
60 * create some dummy annotation derived from the sequence
64 public static void createAnnotation(SequenceI sq)
66 Annotation[] al = new Annotation[sq.getLength()];
67 for (int i = 0; i < al.length; i++)
69 al[i] = new Annotation(new Annotation("" + sq.getCharAt(i), "",
70 (char) 0, sq.findPosition(i)));
72 AlignmentAnnotation alan = new AlignmentAnnotation(
73 "For " + sq.getName(), "Fake alignment annot", al);
74 // create a sequence mapping for the annotation vector in its current state
75 alan.createSequenceMapping(sq, sq.getStart(), false);
76 alan.setProperty("CreatedBy", "createAnnotation");
77 sq.addAlignmentAnnotation(alan);
81 * use this to test annotation derived from method above as it is transferred
82 * across different sequences derived from same dataset coordinate frame
86 public static void testAnnotTransfer(AlignmentAnnotation ala)
89 "Failed - need annotation created by createAnnotation method",
90 ala.description, "Fake alignment annot");
91 ala.adjustForAlignment();
92 for (int p = 0; p < ala.annotations.length; p++)
94 if (ala.annotations[p] != null)
97 "Mismatch at position " + p
98 + " between annotation position value and sequence"
100 (int) ala.annotations[p].value,
101 ala.sequenceRef.findPosition(p));
107 * Tests the liftOver method and also exercises the functions for remapping
108 * annotation across different reference sequences. Here, the test is between
109 * different dataset frames (annotation transferred by mapping between
112 @Test(groups = { "Functional" })
113 public void testLiftOver()
115 SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
117 sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
118 SequenceI sqTo = new Sequence("toShort", "RCDEW");
120 sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
121 createAnnotation(sqTo);
122 AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
123 createAnnotation(sqFrom);
124 AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
125 AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo,
127 SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
128 alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
129 alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
130 alSeq1.setDatasetSequence(sqFrom);
131 SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
132 alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
133 alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
134 alSeq2.setDatasetSequence(sqTo);
135 System.out.println(new AppletFormatAdapter().formatSequences(
136 FileFormat.Stockholm, new Alignment(new SequenceI[]
137 { sqFrom, alSeq1, sqTo, alSeq2 }), true));
139 Mapping mp = align.getMappingFromS1(false);
141 AlignmentAnnotation almap1 = new AlignmentAnnotation(
142 sqTo.getAnnotation()[0]);
143 almap1.liftOver(sqFrom, mp);
144 assertEquals(almap1.sequenceRef, sqFrom);
145 alSeq1.addAlignmentAnnotation(almap1);
146 almap1.setSequenceRef(alSeq1);
147 almap1.adjustForAlignment();
148 AlignmentAnnotation almap2 = new AlignmentAnnotation(
149 sqFrom.getAnnotation()[0]);
150 almap2.liftOver(sqTo, mp);
151 assertEquals(almap2.sequenceRef, sqTo);
153 alSeq2.addAlignmentAnnotation(almap2);
154 almap2.setSequenceRef(alSeq2);
155 almap2.adjustForAlignment();
157 AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
158 all.addAnnotation(almap1);
159 all.addAnnotation(almap2);
160 System.out.println(new AppletFormatAdapter()
161 .formatSequences(FileFormat.Stockholm, all, true));
163 for (int p = 0; p < alSeq1.getLength(); p++)
165 Annotation orig1, trans1, orig2, trans2;
166 trans2 = almap2.annotations[p];
167 orig2 = origFrom.annotations[alSeq1.findPosition(p)
168 - sqFrom.getStart()];
169 orig1 = origTo.annotations[alSeq2.findPosition(p) - sqTo.getStart()];
170 trans1 = almap1.annotations[p];
171 if (trans1 == trans2)
173 System.out.println("Pos " + p + " mismatch");
177 "Mismatch on Original From and transferred annotation on 2",
178 (orig2 != null) ? orig2.toString() : null,
179 (trans2 != null) ? trans2.toString() : null);
181 "Mismatch on Original To and transferred annotation on 1",
182 (orig1 != null) ? orig1.toString() : null,
183 (trans1 != null) ? trans1.toString() : null);
184 String alm1 = "" + (almap1.annotations.length > p
185 ? almap1.annotations[p].displayCharacter
187 String alm2 = "" + (almap2.annotations.length > p
188 ? almap2.annotations[p].displayCharacter
190 assertEquals("Position " + p + " " + alm1 + " " + alm2, alm1, alm2);
194 @Test(groups = { "Functional" })
195 public void testAdjustForAlignment()
197 SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
198 seq.createDatasetSequence();
201 * Annotate positions 3/4/5 (CDE) with values 1/2/3
203 Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
204 new Annotation(2), new Annotation(3) };
205 AlignmentAnnotation ann = new AlignmentAnnotation("SS",
206 "secondary structure", anns);
207 seq.addAlignmentAnnotation(ann);
210 * Check annotation map before modifying aligned sequence
212 assertNull(ann.getAnnotationForPosition(1));
213 assertNull(ann.getAnnotationForPosition(2));
214 assertNull(ann.getAnnotationForPosition(6));
215 assertNull(ann.getAnnotationForPosition(7));
216 assertEquals(1, ann.getAnnotationForPosition(3).value, 0.001d);
217 assertEquals(2, ann.getAnnotationForPosition(4).value, 0.001d);
218 assertEquals(3, ann.getAnnotationForPosition(5).value, 0.001d);
221 * Trim the displayed sequence to BCD and adjust annotations
223 seq.setSequence("BCD");
226 ann.adjustForAlignment();
229 * Should now have annotations for aligned positions 2, 3Q (CD) only
231 assertEquals(3, ann.annotations.length);
232 assertNull(ann.annotations[0]);
233 assertEquals(1, ann.annotations[1].value, 0.001);
234 assertEquals(2, ann.annotations[2].value, 0.001);
238 * Test the method that defaults rna symbol to the one matching the preceding
239 * unmatched opening bracket (if any)
241 @Test(groups = { "Functional" })
242 public void testGetDefaultRnaHelixSymbol()
244 AlignmentAnnotation ann = new AlignmentAnnotation("SS",
245 "secondary structure", null);
246 assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
248 Annotation[] anns = new Annotation[20];
249 ann.annotations = anns;
250 assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
252 anns[1] = new Annotation("(", "S", '(', 0f);
253 assertEquals("(", ann.getDefaultRnaHelixSymbol(0));
254 assertEquals("(", ann.getDefaultRnaHelixSymbol(1));
255 assertEquals(")", ann.getDefaultRnaHelixSymbol(2));
256 assertEquals(")", ann.getDefaultRnaHelixSymbol(3));
261 anns[1] = new Annotation("(", "S", '(', 0f);
262 anns[3] = new Annotation("[", "S", '[', 0f);
263 anns[5] = new Annotation("{", "S", '{', 0f);
264 anns[7] = new Annotation("<", "S", '<', 0f);
265 anns[9] = new Annotation("}", "S", '}', 0f);
266 anns[11] = new Annotation(">", "S", '>', 0f);
267 anns[13] = new Annotation(")", "S", ')', 0f);
268 anns[15] = new Annotation("]", "S", ']', 0f);
270 String expected = "(())]]}}>>>>]]]](";
271 for (int i = 0; i < expected.length(); i++)
273 assertEquals("column " + i, String.valueOf(expected.charAt(i)),
274 ann.getDefaultRnaHelixSymbol(i));
278 * .(.[.(.).{.}.<.].D.
280 anns[1] = new Annotation("(", "S", '(', 0f);
281 anns[3] = new Annotation("[", "S", '[', 0f);
282 anns[5] = new Annotation("(", "S", '(', 0f);
283 anns[7] = new Annotation(")", "S", ')', 0f);
284 anns[9] = new Annotation("{", "S", '{', 0f);
285 anns[11] = new Annotation("}", "S", '}', 0f);
286 anns[13] = new Annotation("<", "S", '>', 0f);
287 anns[15] = new Annotation("]", "S", ']', 0f);
288 anns[17] = new Annotation("D", "S", 'D', 0f);
290 expected = "(())]]))]]}}]]>>>>dd";
291 for (int i = 0; i < expected.length(); i++)
293 assertEquals("column " + i, String.valueOf(expected.charAt(i)),
294 ann.getDefaultRnaHelixSymbol(i));
298 public static Annotation newAnnotation(String ann)
303 val = Float.parseFloat(ann);
304 } catch (NumberFormatException q)
308 return new Annotation(ann, ann, '\0', val);
311 @Test(groups = { "Functional" })
312 public void testIsQuantitative()
314 AlignmentAnnotation ann = null;
316 ann = new AlignmentAnnotation("an", "some an", null);
317 Assert.assertFalse(ann.isQuantitative(),
318 "Empty annotation set should not be quantitative.");
320 ann = new AlignmentAnnotation("an", "some an",
322 { newAnnotation("4"), newAnnotation("1"), newAnnotation("1"),
323 newAnnotation("0.1"), newAnnotation("0.3") });
324 Assert.assertTrue(ann.isQuantitative(),
325 "All numbers annotation set should be quantitative.");
327 ann = new AlignmentAnnotation("an", "some an",
329 { newAnnotation("E"), newAnnotation("E"), newAnnotation("E"),
330 newAnnotation("E"), newAnnotation("E") });
331 Assert.assertFalse(ann.isQuantitative(),
332 "All 'E' annotation set should not be quantitative.");
334 ann = new AlignmentAnnotation("an", "some an",
336 { newAnnotation("E"), newAnnotation("1"), newAnnotation("2"),
337 newAnnotation("3"), newAnnotation("E") });
338 Assert.assertTrue(ann.isQuantitative(),
339 "Mixed 'E' annotation set should be quantitative.");
342 @Test(groups = "Functional")
343 public void testMakeVisibleAnnotation()
345 HiddenColumns h = new HiddenColumns();
346 Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
347 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
348 new Annotation(5), new Annotation(6), new Annotation(7),
350 AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
354 AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann",
356 emptyann.makeVisibleAnnotation(h);
357 assertNull(emptyann.annotations);
359 emptyann.makeVisibleAnnotation(3, 4, h);
360 assertNull(emptyann.annotations);
362 // without bounds, does everything
363 ann.makeVisibleAnnotation(h);
364 assertEquals(12, ann.annotations.length);
365 assertNull(ann.annotations[0]);
366 assertNull(ann.annotations[1]);
367 assertEquals(1.0f, ann.annotations[2].value);
368 assertEquals(2.0f, ann.annotations[3].value);
369 assertEquals(3.0f, ann.annotations[4].value);
370 assertNull(ann.annotations[5]);
371 assertNull(ann.annotations[6]);
372 assertEquals(4.0f, ann.annotations[7].value);
373 assertEquals(5.0f, ann.annotations[8].value);
374 assertEquals(6.0f, ann.annotations[9].value);
375 assertEquals(7.0f, ann.annotations[10].value);
376 assertEquals(8.0f, ann.annotations[11].value);
378 // without hidden cols, just truncates
379 ann.makeVisibleAnnotation(3, 5, h);
380 assertEquals(3, ann.annotations.length);
381 assertEquals(2.0f, ann.annotations[0].value);
382 assertEquals(3.0f, ann.annotations[1].value);
383 assertNull(ann.annotations[2]);
385 anns = new Annotation[] { null, null, new Annotation(1),
386 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
387 new Annotation(5), new Annotation(6), new Annotation(7),
389 ann = new AlignmentAnnotation("an", "some an", anns);
391 ann.makeVisibleAnnotation(1, 9, h);
392 assertEquals(5, ann.annotations.length);
393 assertNull(ann.annotations[0]);
394 assertEquals(1.0f, ann.annotations[1].value);
395 assertEquals(2.0f, ann.annotations[2].value);
396 assertEquals(5.0f, ann.annotations[3].value);
397 assertEquals(6.0f, ann.annotations[4].value);
399 anns = new Annotation[] { null, null, new Annotation(1),
400 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
401 new Annotation(5), new Annotation(6), new Annotation(7),
403 ann = new AlignmentAnnotation("an", "some an", anns);
405 ann.makeVisibleAnnotation(1, 9, h);
406 assertEquals(3, ann.annotations.length);
407 assertEquals(2.0f, ann.annotations[0].value);
408 assertEquals(5.0f, ann.annotations[1].value);
409 assertEquals(6.0f, ann.annotations[2].value);
411 anns = new Annotation[] { null, null, new Annotation(1),
412 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
413 new Annotation(5), new Annotation(6), new Annotation(7),
414 new Annotation(8), new Annotation(9), new Annotation(10),
415 new Annotation(11), new Annotation(12), new Annotation(13),
416 new Annotation(14), new Annotation(15) };
417 ann = new AlignmentAnnotation("an", "some an", anns);
418 h = new HiddenColumns();
419 h.hideColumns(5, 18);
420 h.hideColumns(20, 21);
421 ann.makeVisibleAnnotation(1, 21, h);
422 assertEquals(5, ann.annotations.length);
423 assertEquals(1.0f, ann.annotations[1].value);
424 assertEquals(2.0f, ann.annotations[2].value);
425 assertEquals(3.0f, ann.annotations[3].value);
426 assertNull(ann.annotations[0]);
427 assertNull(ann.annotations[4]);