Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
AlignmentAnnotationTests | 37 | 204 | 25 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
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. | |
11 | * | |
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. | |
16 | * | |
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. | |
20 | */ | |
21 | package jalview.datamodel; | |
22 | ||
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; | |
27 | ||
28 | import jalview.analysis.AlignSeq; | |
29 | import jalview.gui.JvOptionPane; | |
30 | import jalview.io.AppletFormatAdapter; | |
31 | import jalview.io.FileFormat; | |
32 | ||
33 | import org.testng.Assert; | |
34 | import org.testng.annotations.BeforeClass; | |
35 | import org.testng.annotations.Test; | |
36 | ||
37 | public class AlignmentAnnotationTests | |
38 | { | |
39 | ||
40 | 1 | @BeforeClass(alwaysRun = true) |
41 | public void setUpJvOptionPane() | |
42 | { | |
43 | 1 | JvOptionPane.setInteractiveMode(false); |
44 | 1 | JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); |
45 | } | |
46 | ||
47 | 1 | @Test(groups = { "Functional" }) |
48 | public void testCopyConstructor() | |
49 | { | |
50 | 1 | SequenceI sq = new Sequence("Foo", "ARAARARARAWEAWEAWRAWEAWE"); |
51 | 1 | createAnnotation(sq); |
52 | 1 | AlignmentAnnotation alc, alo = sq.getAnnotation()[0]; |
53 | 1 | alc = new AlignmentAnnotation(alo); |
54 | 1 | for (String key : alo.getProperties()) |
55 | { | |
56 | 1 | assertEquals("Property mismatch", alo.getProperty(key), |
57 | alc.getProperty(key)); | |
58 | } | |
59 | } | |
60 | ||
61 | /** | |
62 | * create some dummy annotation derived from the sequence | |
63 | * | |
64 | * @param sq | |
65 | */ | |
66 | 3 | public static void createAnnotation(SequenceI sq) |
67 | { | |
68 | 3 | Annotation[] al = new Annotation[sq.getLength()]; |
69 | 41 | for (int i = 0; i < al.length; i++) |
70 | { | |
71 | 38 | al[i] = new Annotation(new Annotation("" + sq.getCharAt(i), "", |
72 | (char) 0, sq.findPosition(i))); | |
73 | } | |
74 | 3 | 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 | 3 | alan.createSequenceMapping(sq, sq.getStart(), false); |
78 | 3 | alan.setProperty("CreatedBy", "createAnnotation"); |
79 | 3 | sq.addAlignmentAnnotation(alan); |
80 | } | |
81 | ||
82 | /** | |
83 | * use this to test annotation derived from method above as it is transferred | |
84 | * across different sequences derived from same dataset coordinate frame | |
85 | * | |
86 | * @param ala | |
87 | */ | |
88 | 0 | public static void testAnnotTransfer(AlignmentAnnotation ala) |
89 | { | |
90 | 0 | assertEquals( |
91 | "Failed - need annotation created by createAnnotation method", | |
92 | ala.description, "Fake alignment annot"); | |
93 | 0 | ala.adjustForAlignment(); |
94 | 0 | for (int p = 0; p < ala.annotations.length; p++) |
95 | { | |
96 | 0 | if (ala.annotations[p] != null) |
97 | { | |
98 | 0 | assertEquals( |
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)); | |
104 | } | |
105 | } | |
106 | } | |
107 | ||
108 | /** | |
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 | |
112 | * sequences) | |
113 | */ | |
114 | 1 | @Test(groups = { "Functional" }) |
115 | public void testLiftOver() | |
116 | { | |
117 | 1 | SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH"); |
118 | 1 | sqFrom.setStart(10); |
119 | 1 | sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1)); |
120 | 1 | SequenceI sqTo = new Sequence("toShort", "RCDEW"); |
121 | 1 | sqTo.setStart(20); |
122 | 1 | sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1)); |
123 | 1 | createAnnotation(sqTo); |
124 | 1 | AlignmentAnnotation origTo = sqTo.getAnnotation()[0]; |
125 | 1 | createAnnotation(sqFrom); |
126 | 1 | AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0]; |
127 | 1 | AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo, |
128 | AlignSeq.PEP); | |
129 | 1 | SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1()); |
130 | 1 | alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1); |
131 | 1 | alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1); |
132 | 1 | alSeq1.setDatasetSequence(sqFrom); |
133 | 1 | SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2()); |
134 | 1 | alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1); |
135 | 1 | alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1); |
136 | 1 | alSeq2.setDatasetSequence(sqTo); |
137 | 1 | System.out.println(new AppletFormatAdapter().formatSequences( |
138 | FileFormat.Stockholm, new Alignment(new SequenceI[] | |
139 | { sqFrom, alSeq1, sqTo, alSeq2 }), true)); | |
140 | ||
141 | 1 | Mapping mp = align.getMappingFromS1(false); |
142 | ||
143 | 1 | AlignmentAnnotation almap1 = new AlignmentAnnotation( |
144 | sqTo.getAnnotation()[0]); | |
145 | 1 | almap1.liftOver(sqFrom, mp); |
146 | 1 | assertEquals(almap1.sequenceRef, sqFrom); |
147 | 1 | alSeq1.addAlignmentAnnotation(almap1); |
148 | 1 | almap1.setSequenceRef(alSeq1); |
149 | 1 | almap1.adjustForAlignment(); |
150 | 1 | AlignmentAnnotation almap2 = new AlignmentAnnotation( |
151 | sqFrom.getAnnotation()[0]); | |
152 | 1 | almap2.liftOver(sqTo, mp); |
153 | 1 | assertEquals(almap2.sequenceRef, sqTo); |
154 | ||
155 | 1 | alSeq2.addAlignmentAnnotation(almap2); |
156 | 1 | almap2.setSequenceRef(alSeq2); |
157 | 1 | almap2.adjustForAlignment(); |
158 | ||
159 | 1 | AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 }); |
160 | 1 | all.addAnnotation(almap1); |
161 | 1 | all.addAnnotation(almap2); |
162 | 1 | System.out.println(new AppletFormatAdapter() |
163 | .formatSequences(FileFormat.Stockholm, all, true)); | |
164 | ||
165 | 6 | for (int p = 0; p < alSeq1.getLength(); p++) |
166 | { | |
167 | 5 | Annotation orig1, trans1, orig2, trans2; |
168 | 5 | trans2 = almap2.annotations[p]; |
169 | 5 | orig2 = origFrom.annotations[alSeq1.findPosition(p) |
170 | - sqFrom.getStart()]; | |
171 | 5 | orig1 = origTo.annotations[alSeq2.findPosition(p) - sqTo.getStart()]; |
172 | 5 | trans1 = almap1.annotations[p]; |
173 | 5 | if (trans1 == trans2) |
174 | { | |
175 | 1 | System.out.println("Pos " + p + " mismatch"); |
176 | 1 | continue; |
177 | } | |
178 | 4 | assertEquals( |
179 | "Mismatch on Original From and transferred annotation on 2", | |
180 | 4 | (orig2 != null) ? orig2.toString() : null, |
181 | 4 | (trans2 != null) ? trans2.toString() : null); |
182 | 4 | assertEquals( |
183 | "Mismatch on Original To and transferred annotation on 1", | |
184 | 4 | (orig1 != null) ? orig1.toString() : null, |
185 | 4 | (trans1 != null) ? trans1.toString() : null); |
186 | 4 | String alm1 = "" + (almap1.annotations.length > p |
187 | ? almap1.annotations[p].displayCharacter | |
188 | : "Out of range"); | |
189 | 4 | String alm2 = "" + (almap2.annotations.length > p |
190 | ? almap2.annotations[p].displayCharacter | |
191 | : "Out of range"); | |
192 | 4 | assertEquals("Position " + p + " " + alm1 + " " + alm2, alm1, alm2); |
193 | } | |
194 | } | |
195 | ||
196 | 1 | @Test(groups = { "Functional" }) |
197 | public void testAdjustForAlignment() | |
198 | { | |
199 | 1 | SequenceI seq = new Sequence("TestSeq", "ABCDEFG"); |
200 | 1 | seq.createDatasetSequence(); |
201 | ||
202 | /* | |
203 | * Annotate positions 3/4/5 (CDE) with values 1/2/3 | |
204 | */ | |
205 | 1 | Annotation[] anns = new Annotation[] { null, null, new Annotation(1), |
206 | new Annotation(2), new Annotation(3) }; | |
207 | 1 | AlignmentAnnotation ann = new AlignmentAnnotation("SS", |
208 | "secondary structure", anns); | |
209 | 1 | seq.addAlignmentAnnotation(ann); |
210 | ||
211 | /* | |
212 | * Check annotation map before modifying aligned sequence | |
213 | */ | |
214 | 1 | assertNull(ann.getAnnotationForPosition(1)); |
215 | 1 | assertNull(ann.getAnnotationForPosition(2)); |
216 | 1 | assertNull(ann.getAnnotationForPosition(6)); |
217 | 1 | assertNull(ann.getAnnotationForPosition(7)); |
218 | 1 | assertEquals(1, ann.getAnnotationForPosition(3).value, 0.001d); |
219 | 1 | assertEquals(2, ann.getAnnotationForPosition(4).value, 0.001d); |
220 | 1 | assertEquals(3, ann.getAnnotationForPosition(5).value, 0.001d); |
221 | ||
222 | /* | |
223 | * Trim the displayed sequence to BCD and adjust annotations | |
224 | */ | |
225 | 1 | seq.setSequence("BCD"); |
226 | 1 | seq.setStart(2); |
227 | 1 | seq.setEnd(4); |
228 | 1 | ann.adjustForAlignment(); |
229 | ||
230 | /* | |
231 | * Should now have annotations for aligned positions 2, 3Q (CD) only | |
232 | */ | |
233 | 1 | assertEquals(3, ann.annotations.length); |
234 | 1 | assertNull(ann.annotations[0]); |
235 | 1 | assertEquals(1, ann.annotations[1].value, 0.001); |
236 | 1 | assertEquals(2, ann.annotations[2].value, 0.001); |
237 | } | |
238 | ||
239 | /** | |
240 | * Test the method that defaults rna symbol to the one matching the preceding | |
241 | * unmatched opening bracket (if any) | |
242 | */ | |
243 | 1 | @Test(groups = { "Functional" }) |
244 | public void testGetDefaultRnaHelixSymbol() | |
245 | { | |
246 | 1 | AlignmentAnnotation ann = new AlignmentAnnotation("SS", |
247 | "secondary structure", null); | |
248 | 1 | assertEquals("(", ann.getDefaultRnaHelixSymbol(4)); |
249 | ||
250 | 1 | Annotation[] anns = new Annotation[20]; |
251 | 1 | ann.annotations = anns; |
252 | 1 | assertEquals("(", ann.getDefaultRnaHelixSymbol(4)); |
253 | ||
254 | 1 | anns[1] = new Annotation("(", "S", '(', 0f); |
255 | 1 | assertEquals("(", ann.getDefaultRnaHelixSymbol(0)); |
256 | 1 | assertEquals("(", ann.getDefaultRnaHelixSymbol(1)); |
257 | 1 | assertEquals(")", ann.getDefaultRnaHelixSymbol(2)); |
258 | 1 | assertEquals(")", ann.getDefaultRnaHelixSymbol(3)); |
259 | ||
260 | /* | |
261 | * .(.[.{.<.}.>.).]. | |
262 | */ | |
263 | 1 | anns[1] = new Annotation("(", "S", '(', 0f); |
264 | 1 | anns[3] = new Annotation("[", "S", '[', 0f); |
265 | 1 | anns[5] = new Annotation("{", "S", '{', 0f); |
266 | 1 | anns[7] = new Annotation("<", "S", '<', 0f); |
267 | 1 | anns[9] = new Annotation("}", "S", '}', 0f); |
268 | 1 | anns[11] = new Annotation(">", "S", '>', 0f); |
269 | 1 | anns[13] = new Annotation(")", "S", ')', 0f); |
270 | 1 | anns[15] = new Annotation("]", "S", ']', 0f); |
271 | ||
272 | 1 | String expected = "(())]]}}>>>>]]]]("; |
273 | 18 | for (int i = 0; i < expected.length(); i++) |
274 | { | |
275 | 17 | assertEquals("column " + i, String.valueOf(expected.charAt(i)), |
276 | ann.getDefaultRnaHelixSymbol(i)); | |
277 | } | |
278 | ||
279 | /* | |
280 | * .(.[.(.).{.}.<.].D. | |
281 | */ | |
282 | 1 | anns[1] = new Annotation("(", "S", '(', 0f); |
283 | 1 | anns[3] = new Annotation("[", "S", '[', 0f); |
284 | 1 | anns[5] = new Annotation("(", "S", '(', 0f); |
285 | 1 | anns[7] = new Annotation(")", "S", ')', 0f); |
286 | 1 | anns[9] = new Annotation("{", "S", '{', 0f); |
287 | 1 | anns[11] = new Annotation("}", "S", '}', 0f); |
288 | 1 | anns[13] = new Annotation("<", "S", '>', 0f); |
289 | 1 | anns[15] = new Annotation("]", "S", ']', 0f); |
290 | 1 | anns[17] = new Annotation("D", "S", 'D', 0f); |
291 | ||
292 | 1 | expected = "(())]]))]]}}]]>>>>dd"; |
293 | 21 | for (int i = 0; i < expected.length(); i++) |
294 | { | |
295 | 20 | assertEquals("column " + i, String.valueOf(expected.charAt(i)), |
296 | ann.getDefaultRnaHelixSymbol(i)); | |
297 | } | |
298 | } | |
299 | ||
300 | 15 | public static Annotation newAnnotation(String ann) |
301 | { | |
302 | 15 | float val = 0f; |
303 | 15 | try |
304 | { | |
305 | 15 | val = Float.parseFloat(ann); |
306 | } catch (NumberFormatException q) | |
307 | { | |
308 | } | |
309 | 15 | ; |
310 | 15 | return new Annotation(ann, ann, '\0', val); |
311 | } | |
312 | ||
313 | 1 | @Test(groups = { "Functional" }) |
314 | public void testIsQuantitative() | |
315 | { | |
316 | 1 | AlignmentAnnotation ann = null; |
317 | ||
318 | 1 | ann = new AlignmentAnnotation("an", "some an", null); |
319 | 1 | Assert.assertFalse(ann.isQuantitative(), |
320 | "Empty annotation set should not be quantitative."); | |
321 | ||
322 | 1 | ann = new AlignmentAnnotation("an", "some an", |
323 | new Annotation[] | |
324 | { newAnnotation("4"), newAnnotation("1"), newAnnotation("1"), | |
325 | newAnnotation("0.1"), newAnnotation("0.3") }); | |
326 | 1 | Assert.assertTrue(ann.isQuantitative(), |
327 | "All numbers annotation set should be quantitative."); | |
328 | ||
329 | 1 | ann = new AlignmentAnnotation("an", "some an", |
330 | new Annotation[] | |
331 | { newAnnotation("E"), newAnnotation("E"), newAnnotation("E"), | |
332 | newAnnotation("E"), newAnnotation("E") }); | |
333 | 1 | Assert.assertFalse(ann.isQuantitative(), |
334 | "All 'E' annotation set should not be quantitative."); | |
335 | ||
336 | 1 | ann = new AlignmentAnnotation("an", "some an", |
337 | new Annotation[] | |
338 | { newAnnotation("E"), newAnnotation("1"), newAnnotation("2"), | |
339 | newAnnotation("3"), newAnnotation("E") }); | |
340 | 1 | Assert.assertTrue(ann.isQuantitative(), |
341 | "Mixed 'E' annotation set should be quantitative."); | |
342 | } | |
343 | ||
344 | 1 | @Test(groups = "Functional") |
345 | public void testMakeVisibleAnnotation() | |
346 | { | |
347 | 1 | HiddenColumns h = new HiddenColumns(); |
348 | 1 | 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), | |
351 | new Annotation(8) }; | |
352 | 1 | AlignmentAnnotation ann = new AlignmentAnnotation("an", "some an", |
353 | anns); | |
354 | ||
355 | // null annotations | |
356 | 1 | AlignmentAnnotation emptyann = new AlignmentAnnotation("an", "some ann", |
357 | null); | |
358 | 1 | emptyann.makeVisibleAnnotation(h); |
359 | 1 | assertNull(emptyann.annotations); |
360 | ||
361 | 1 | emptyann.makeVisibleAnnotation(3, 4, h); |
362 | 1 | assertNull(emptyann.annotations); |
363 | ||
364 | // without bounds, does everything | |
365 | 1 | ann.makeVisibleAnnotation(h); |
366 | 1 | assertEquals(12, ann.annotations.length); |
367 | 1 | assertNull(ann.annotations[0]); |
368 | 1 | assertNull(ann.annotations[1]); |
369 | 1 | assertEquals(1.0f, ann.annotations[2].value); |
370 | 1 | assertEquals(2.0f, ann.annotations[3].value); |
371 | 1 | assertEquals(3.0f, ann.annotations[4].value); |
372 | 1 | assertNull(ann.annotations[5]); |
373 | 1 | assertNull(ann.annotations[6]); |
374 | 1 | assertEquals(4.0f, ann.annotations[7].value); |
375 | 1 | assertEquals(5.0f, ann.annotations[8].value); |
376 | 1 | assertEquals(6.0f, ann.annotations[9].value); |
377 | 1 | assertEquals(7.0f, ann.annotations[10].value); |
378 | 1 | assertEquals(8.0f, ann.annotations[11].value); |
379 | ||
380 | // without hidden cols, just truncates | |
381 | 1 | ann.makeVisibleAnnotation(3, 5, h); |
382 | 1 | assertEquals(3, ann.annotations.length); |
383 | 1 | assertEquals(2.0f, ann.annotations[0].value); |
384 | 1 | assertEquals(3.0f, ann.annotations[1].value); |
385 | 1 | assertNull(ann.annotations[2]); |
386 | ||
387 | 1 | 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), | |
390 | new Annotation(8) }; | |
391 | 1 | ann = new AlignmentAnnotation("an", "some an", anns); |
392 | 1 | h.hideColumns(4, 7); |
393 | 1 | ann.makeVisibleAnnotation(1, 9, h); |
394 | 1 | assertEquals(5, ann.annotations.length); |
395 | 1 | assertNull(ann.annotations[0]); |
396 | 1 | assertEquals(1.0f, ann.annotations[1].value); |
397 | 1 | assertEquals(2.0f, ann.annotations[2].value); |
398 | 1 | assertEquals(5.0f, ann.annotations[3].value); |
399 | 1 | assertEquals(6.0f, ann.annotations[4].value); |
400 | ||
401 | 1 | 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), | |
404 | new Annotation(8) }; | |
405 | 1 | ann = new AlignmentAnnotation("an", "some an", anns); |
406 | 1 | h.hideColumns(1, 2); |
407 | 1 | ann.makeVisibleAnnotation(1, 9, h); |
408 | 1 | assertEquals(3, ann.annotations.length); |
409 | 1 | assertEquals(2.0f, ann.annotations[0].value); |
410 | 1 | assertEquals(5.0f, ann.annotations[1].value); |
411 | 1 | assertEquals(6.0f, ann.annotations[2].value); |
412 | ||
413 | 1 | 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 | 1 | ann = new AlignmentAnnotation("an", "some an", anns); |
420 | 1 | h = new HiddenColumns(); |
421 | 1 | h.hideColumns(5, 18); |
422 | 1 | h.hideColumns(20, 21); |
423 | 1 | ann.makeVisibleAnnotation(1, 21, h); |
424 | 1 | assertEquals(5, ann.annotations.length); |
425 | 1 | assertEquals(1.0f, ann.annotations[1].value); |
426 | 1 | assertEquals(2.0f, ann.annotations[2].value); |
427 | 1 | assertEquals(3.0f, ann.annotations[3].value); |
428 | 1 | assertNull(ann.annotations[0]); |
429 | 1 | assertNull(ann.annotations[4]); |
430 | } | |
431 | ||
432 | /** | |
433 | * test the contact matrix nogroups property methods | |
434 | */ | |
435 | 1 | @Test(groups = { "Functional" }) |
436 | public void test_contactMatrixGroups() | |
437 | { | |
438 | 1 | AlignmentAnnotation aa = new AlignmentAnnotation("foo", "foo desc", |
439 | null); | |
440 | 1 | assertTrue(aa.isShowGroupsForContactMatrix()); |
441 | 1 | aa.setShowGroupsForContactMatrix(false); |
442 | 1 | assertFalse(aa.isShowGroupsForContactMatrix()); |
443 | 1 | AlignmentAnnotation copy = new AlignmentAnnotation(aa); |
444 | 1 | assertFalse(copy.isShowGroupsForContactMatrix()); |
445 | 1 | aa.setShowGroupsForContactMatrix(true); |
446 | 1 | assertTrue(aa.isShowGroupsForContactMatrix()); |
447 | // copy should not be updated | |
448 | 1 | assertFalse(copy.isShowGroupsForContactMatrix()); |
449 | ||
450 | } | |
451 | } |