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("For "
73 + 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)
96 assertEquals("Mismatch at position " + p
97 + " between annotation position value and sequence"
98 + ala.annotations[p], (int) ala.annotations[p].value,
99 ala.sequenceRef.findPosition(p));
105 * Tests the liftOver method and also exercises the functions for remapping
106 * annotation across different reference sequences. Here, the test is between
107 * different dataset frames (annotation transferred by mapping between
110 @Test(groups = { "Functional" })
111 public void testLiftOver()
113 SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
115 sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
116 SequenceI sqTo = new Sequence("toShort", "RCDEW");
118 sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
119 createAnnotation(sqTo);
120 AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
121 createAnnotation(sqFrom);
122 AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
123 AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo,
125 SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
126 alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
127 alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
128 alSeq1.setDatasetSequence(sqFrom);
129 SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
130 alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
131 alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
132 alSeq2.setDatasetSequence(sqTo);
133 System.out.println(new AppletFormatAdapter()
135 FileFormat.Stockholm, new Alignment(new SequenceI[] { sqFrom,
136 alSeq1, sqTo, alSeq2 }), true));
138 Mapping mp = align.getMappingFromS1(false);
140 AlignmentAnnotation almap1 = new AlignmentAnnotation(
141 sqTo.getAnnotation()[0]);
142 almap1.liftOver(sqFrom, mp);
143 assertEquals(almap1.sequenceRef, sqFrom);
144 alSeq1.addAlignmentAnnotation(almap1);
145 almap1.setSequenceRef(alSeq1);
146 almap1.adjustForAlignment();
147 AlignmentAnnotation almap2 = new AlignmentAnnotation(
148 sqFrom.getAnnotation()[0]);
149 almap2.liftOver(sqTo, mp);
150 assertEquals(almap2.sequenceRef, sqTo);
152 alSeq2.addAlignmentAnnotation(almap2);
153 almap2.setSequenceRef(alSeq2);
154 almap2.adjustForAlignment();
156 AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
157 all.addAnnotation(almap1);
158 all.addAnnotation(almap2);
159 System.out.println(new AppletFormatAdapter().formatSequences(
160 FileFormat.Stockholm,
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);
185 + (almap1.annotations.length > p ? almap1.annotations[p].displayCharacter
188 + (almap2.annotations.length > p ? 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", new Annotation[] {
321 newAnnotation("4"), newAnnotation("1"), newAnnotation("1"),
322 newAnnotation("0.1"), newAnnotation("0.3") });
323 Assert.assertTrue(ann.isQuantitative(),
324 "All numbers annotation set should be quantitative.");
326 ann = new AlignmentAnnotation("an", "some an", new Annotation[] {
327 newAnnotation("E"), newAnnotation("E"), newAnnotation("E"),
328 newAnnotation("E"), newAnnotation("E") });
329 Assert.assertFalse(ann.isQuantitative(),
330 "All 'E' annotation set should not be quantitative.");
332 ann = new AlignmentAnnotation("an", "some an", new Annotation[] {
333 newAnnotation("E"), newAnnotation("1"), newAnnotation("2"),
334 newAnnotation("3"), newAnnotation("E") });
335 Assert.assertTrue(ann.isQuantitative(),
336 "Mixed 'E' annotation set should be quantitative.");
339 @Test(groups = "Functional")
340 public void testMakeVisibleAnnotation()
342 HiddenColumns h = new HiddenColumns();
343 Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
344 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
345 new Annotation(5), new Annotation(6), new Annotation(7),
347 AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an",
351 AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann",
353 emptyann.makeVisibleAnnotation(h);
354 assertNull(emptyann.annotations);
356 emptyann.makeVisibleAnnotation(3, 4, h);
357 assertNull(emptyann.annotations);
359 // without bounds, does everything
360 ann.makeVisibleAnnotation(h);
361 assertEquals(12, ann.annotations.length);
362 assertNull(ann.annotations[0]);
363 assertNull(ann.annotations[1]);
364 assertEquals(1.0f, ann.annotations[2].value);
365 assertEquals(2.0f, ann.annotations[3].value);
366 assertEquals(3.0f, ann.annotations[4].value);
367 assertNull(ann.annotations[5]);
368 assertNull(ann.annotations[6]);
369 assertEquals(4.0f, ann.annotations[7].value);
370 assertEquals(5.0f, ann.annotations[8].value);
371 assertEquals(6.0f, ann.annotations[9].value);
372 assertEquals(7.0f, ann.annotations[10].value);
373 assertEquals(8.0f, ann.annotations[11].value);
375 // without hidden cols, just truncates
376 ann.makeVisibleAnnotation(3, 5, h);
377 assertEquals(3, ann.annotations.length);
378 assertEquals(2.0f, ann.annotations[0].value);
379 assertEquals(3.0f, ann.annotations[1].value);
380 assertNull(ann.annotations[2]);
382 anns = new Annotation[] { null, null, new Annotation(1),
383 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
384 new Annotation(5), new Annotation(6), new Annotation(7),
386 ann = new AlignmentAnnotation("an", "some an", anns);
388 ann.makeVisibleAnnotation(1, 9, h);
389 assertEquals(5, ann.annotations.length);
390 assertNull(ann.annotations[0]);
391 assertEquals(1.0f, ann.annotations[1].value);
392 assertEquals(2.0f, ann.annotations[2].value);
393 assertEquals(5.0f, ann.annotations[3].value);
394 assertEquals(6.0f, ann.annotations[4].value);
396 anns = new Annotation[] { null, null, new Annotation(1),
397 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
398 new Annotation(5), new Annotation(6), new Annotation(7),
400 ann = new AlignmentAnnotation("an", "some an", anns);
402 ann.makeVisibleAnnotation(1, 9, h);
403 assertEquals(3, ann.annotations.length);
404 assertEquals(2.0f, ann.annotations[0].value);
405 assertEquals(5.0f, ann.annotations[1].value);
406 assertEquals(6.0f, ann.annotations[2].value);
408 anns = new Annotation[] { null, null, new Annotation(1),
409 new Annotation(2), new Annotation(3), null, null, new Annotation(4),
410 new Annotation(5), new Annotation(6), new Annotation(7),
411 new Annotation(8), new Annotation(9), new Annotation(10),
412 new Annotation(11), new Annotation(12), new Annotation(13),
413 new Annotation(14), new Annotation(15) };
414 ann = new AlignmentAnnotation("an", "some an", anns);
415 h = new HiddenColumns();
416 h.hideColumns(5, 18);
417 h.hideColumns(20, 21);
418 ann.makeVisibleAnnotation(1, 21, h);
419 assertEquals(5, ann.annotations.length);
420 assertEquals(1.0f, ann.annotations[1].value);
421 assertEquals(2.0f, ann.annotations[2].value);
422 assertEquals(3.0f, ann.annotations[3].value);
423 assertNull(ann.annotations[0]);
424 assertNull(ann.annotations[4]);