Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
AlignedCodonFrameTest | 41 | 285 | 14 |
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.AssertJUnit.assertEquals; | |
24 | import static org.testng.AssertJUnit.assertFalse; | |
25 | import static org.testng.AssertJUnit.assertNotNull; | |
26 | import static org.testng.AssertJUnit.assertNull; | |
27 | import static org.testng.AssertJUnit.assertSame; | |
28 | import static org.testng.AssertJUnit.assertTrue; | |
29 | import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals; | |
30 | ||
31 | import java.util.Arrays; | |
32 | import java.util.List; | |
33 | ||
34 | import org.testng.annotations.BeforeClass; | |
35 | import org.testng.annotations.Test; | |
36 | ||
37 | import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping; | |
38 | import jalview.gui.JvOptionPane; | |
39 | import jalview.util.MapList; | |
40 | ||
41 | public class AlignedCodonFrameTest | |
42 | { | |
43 | ||
44 | 1 | @BeforeClass(alwaysRun = true) |
45 | public void setUpJvOptionPane() | |
46 | { | |
47 | 1 | JvOptionPane.setInteractiveMode(false); |
48 | 1 | JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); |
49 | } | |
50 | ||
51 | /** | |
52 | * Test the method that locates the first aligned sequence that has a mapping. | |
53 | */ | |
54 | 1 | @Test(groups = { "Functional" }) |
55 | public void testFindAlignedSequence() | |
56 | { | |
57 | 1 | AlignmentI cdna = new Alignment(new SequenceI[] {}); |
58 | 1 | final Sequence seq1 = new Sequence("Seq1", "C-G-TA-GC"); |
59 | 1 | seq1.createDatasetSequence(); |
60 | 1 | cdna.addSequence(seq1); |
61 | 1 | final Sequence seq2 = new Sequence("Seq2", "-TA-GG-GG"); |
62 | 1 | seq2.createDatasetSequence(); |
63 | 1 | cdna.addSequence(seq2); |
64 | ||
65 | 1 | AlignmentI aa = new Alignment(new SequenceI[] {}); |
66 | 1 | final Sequence aseq1 = new Sequence("Seq1", "-P-R"); |
67 | 1 | aseq1.createDatasetSequence(); |
68 | 1 | aa.addSequence(aseq1); |
69 | 1 | final Sequence aseq2 = new Sequence("Seq2", "-LY-"); |
70 | 1 | aseq2.createDatasetSequence(); |
71 | 1 | aa.addSequence(aseq2); |
72 | ||
73 | /* | |
74 | * Mapping from first DNA sequence to second AA sequence. | |
75 | */ | |
76 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
77 | ||
78 | 1 | assertNull(acf.findAlignedSequence(seq1, aa)); |
79 | ||
80 | 1 | MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1); |
81 | 1 | acf.addMap(seq1.getDatasetSequence(), aseq2.getDatasetSequence(), map); |
82 | ||
83 | /* | |
84 | * DNA seq1 maps to AA seq2 | |
85 | */ | |
86 | 1 | assertEquals(aa.getSequenceAt(1), acf.findAlignedSequence( |
87 | cdna.getSequenceAt(0).getDatasetSequence(), aa)); | |
88 | // can also find this from the dna aligned sequence | |
89 | 1 | assertEquals(aa.getSequenceAt(1), |
90 | acf.findAlignedSequence(cdna.getSequenceAt(0), aa)); | |
91 | ||
92 | 1 | assertEquals(cdna.getSequenceAt(0), acf.findAlignedSequence( |
93 | aa.getSequenceAt(1).getDatasetSequence(), cdna)); | |
94 | } | |
95 | ||
96 | /** | |
97 | * Test the method that locates the mapped codon for a protein position. | |
98 | */ | |
99 | 1 | @Test(groups = { "Functional" }) |
100 | public void testGetMappedRegion() | |
101 | { | |
102 | // introns lower case, exons upper case | |
103 | 1 | final Sequence dna1 = new Sequence("Seq1/10-18", "c-G-TA-gC-gT-T"); |
104 | 1 | dna1.createDatasetSequence(); |
105 | 1 | final Sequence dna2 = new Sequence("Seq2/20-28", "-TA-gG-Gg-CG-a"); |
106 | 1 | dna2.createDatasetSequence(); |
107 | ||
108 | 1 | final Sequence pep1 = new Sequence("Seq1/3-4", "-P-R"); |
109 | 1 | pep1.createDatasetSequence(); |
110 | 1 | final Sequence pep2 = new Sequence("Seq2/7-9", "-LY-Q"); |
111 | 1 | pep2.createDatasetSequence(); |
112 | ||
113 | /* | |
114 | * First with no mappings | |
115 | */ | |
116 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
117 | ||
118 | 1 | assertNull(acf.getMappedRegion(dna1, pep1, 3)); |
119 | ||
120 | /* | |
121 | * Set up the mappings for the exons (upper-case bases) | |
122 | * Note residue Q is unmapped | |
123 | */ | |
124 | 1 | MapList map1 = new MapList(new int[] { 11, 13, 15, 15, 17, 18 }, |
125 | new int[] | |
126 | { 3, 4 }, 3, 1); | |
127 | 1 | acf.addMap(dna1.getDatasetSequence(), pep1.getDatasetSequence(), map1); |
128 | 1 | MapList map2 = new MapList(new int[] { 20, 21, 23, 24, 26, 27 }, |
129 | new int[] | |
130 | { 7, 9 }, 3, 1); | |
131 | 1 | acf.addMap(dna2.getDatasetSequence(), pep2.getDatasetSequence(), map2); |
132 | ||
133 | /* | |
134 | * get codon positions for peptide position | |
135 | */ | |
136 | 1 | assertArrayEquals(new int[] { 11, 13 }, |
137 | acf.getMappedRegion(dna1, pep1, 3)); | |
138 | 1 | assertArrayEquals(new int[] { 15, 15, 17, 18 }, |
139 | acf.getMappedRegion(dna1, pep1, 4)); | |
140 | 1 | assertArrayEquals(new int[] { 20, 21, 23, 23 }, |
141 | acf.getMappedRegion(dna2, pep2, 7)); | |
142 | 1 | assertArrayEquals(new int[] { 24, 24, 26, 27 }, |
143 | acf.getMappedRegion(dna2, pep2, 8)); | |
144 | ||
145 | /* | |
146 | * No mapping from dna2 to Q | |
147 | */ | |
148 | 1 | assertNull(acf.getMappedRegion(dna2, pep2, 9)); |
149 | ||
150 | /* | |
151 | * No mapping from dna1 to pep2 | |
152 | */ | |
153 | 1 | assertNull(acf.getMappedRegion(dna1, pep2, 7)); |
154 | ||
155 | /* | |
156 | * get peptide position for codon position | |
157 | */ | |
158 | 1 | assertArrayEquals(new int[] { 3, 3 }, |
159 | acf.getMappedRegion(pep1, dna1, 11)); | |
160 | 1 | assertArrayEquals(new int[] { 3, 3 }, |
161 | acf.getMappedRegion(pep1, dna1, 12)); | |
162 | 1 | assertArrayEquals(new int[] { 3, 3 }, |
163 | acf.getMappedRegion(pep1, dna1, 13)); | |
164 | 1 | assertNull(acf.getMappedRegion(pep1, dna1, 14)); // intron base, not mapped |
165 | ||
166 | } | |
167 | ||
168 | 1 | @Test(groups = { "Functional" }) |
169 | public void testGetMappedCodons() | |
170 | { | |
171 | 1 | final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T"); |
172 | 1 | seq1.createDatasetSequence(); |
173 | 1 | final Sequence aseq1 = new Sequence("Seq1", "-V-L"); |
174 | 1 | aseq1.createDatasetSequence(); |
175 | ||
176 | /* | |
177 | * First with no mappings | |
178 | */ | |
179 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
180 | ||
181 | 1 | assertNull(acf.getMappedCodons(seq1.getDatasetSequence(), 0)); |
182 | ||
183 | /* | |
184 | * Set up the mappings for the exons (upper-case bases) | |
185 | */ | |
186 | 1 | MapList map = new MapList(new int[] { 2, 4, 6, 6, 8, 9 }, |
187 | new int[] | |
188 | { 1, 2 }, 3, 1); | |
189 | 1 | acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map); |
190 | ||
191 | 1 | assertEquals(1, |
192 | acf.getMappedCodons(aseq1.getDatasetSequence(), 1).size()); | |
193 | 1 | assertEquals("[G, T, A]", Arrays.toString( |
194 | acf.getMappedCodons(aseq1.getDatasetSequence(), 1).get(0))); | |
195 | 1 | assertEquals("[C, T, T]", Arrays.toString( |
196 | acf.getMappedCodons(aseq1.getDatasetSequence(), 2).get(0))); | |
197 | } | |
198 | ||
199 | /** | |
200 | * Test for the case where there is more than one variant of the DNA mapping | |
201 | * to a protein sequence | |
202 | */ | |
203 | 1 | @Test(groups = { "Functional" }) |
204 | public void testGetMappedCodons_dnaVariants() | |
205 | { | |
206 | 1 | final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T"); |
207 | 1 | seq1.createDatasetSequence(); |
208 | 1 | final Sequence seq2 = new Sequence("Seq2", "c-G-TT-gT-gT-A"); |
209 | 1 | seq2.createDatasetSequence(); |
210 | 1 | final Sequence aseq1 = new Sequence("Seq1", "-V-L"); |
211 | 1 | aseq1.createDatasetSequence(); |
212 | ||
213 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
214 | ||
215 | /* | |
216 | * Set up the mappings for the exons (upper-case bases) | |
217 | */ | |
218 | 1 | MapList map = new MapList(new int[] { 2, 4, 6, 6, 8, 9 }, |
219 | new int[] | |
220 | { 1, 2 }, 3, 1); | |
221 | 1 | acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map); |
222 | 1 | acf.addMap(seq2.getDatasetSequence(), aseq1.getDatasetSequence(), map); |
223 | ||
224 | 1 | assertEquals(2, |
225 | acf.getMappedCodons(aseq1.getDatasetSequence(), 1).size()); | |
226 | 1 | List<char[]> codonsForV = acf |
227 | .getMappedCodons(aseq1.getDatasetSequence(), 1); | |
228 | 1 | assertEquals("[G, T, A]", Arrays.toString(codonsForV.get(0))); |
229 | 1 | assertEquals("[G, T, T]", Arrays.toString(codonsForV.get(1))); |
230 | 1 | List<char[]> codonsForL = acf |
231 | .getMappedCodons(aseq1.getDatasetSequence(), 2); | |
232 | 1 | assertEquals("[C, T, T]", Arrays.toString(codonsForL.get(0))); |
233 | 1 | assertEquals("[T, T, A]", Arrays.toString(codonsForL.get(1))); |
234 | } | |
235 | ||
236 | /** | |
237 | * Test for the case where sequences have start > 1 | |
238 | */ | |
239 | 1 | @Test(groups = { "Functional" }) |
240 | public void testGetMappedCodons_forSubSequences() | |
241 | { | |
242 | 1 | final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T", 27, 35); |
243 | 1 | seq1.createDatasetSequence(); |
244 | ||
245 | 1 | final Sequence aseq1 = new Sequence("Seq1", "-V-L", 12, 13); |
246 | 1 | aseq1.createDatasetSequence(); |
247 | ||
248 | /* | |
249 | * Set up the mappings for the exons (upper-case bases) | |
250 | */ | |
251 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
252 | 1 | MapList map = new MapList(new int[] { 28, 30, 32, 32, 34, 35 }, |
253 | new int[] | |
254 | { 12, 13 }, 3, 1); | |
255 | 1 | acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map); |
256 | ||
257 | 1 | assertEquals("[G, T, A]", Arrays.toString( |
258 | acf.getMappedCodons(aseq1.getDatasetSequence(), 12).get(0))); | |
259 | 1 | assertEquals("[C, T, T]", Arrays.toString( |
260 | acf.getMappedCodons(aseq1.getDatasetSequence(), 13).get(0))); | |
261 | } | |
262 | ||
263 | 1 | @Test(groups = { "Functional" }) |
264 | public void testCouldReplaceSequence() | |
265 | { | |
266 | 1 | SequenceI seq1 = new Sequence("Seq1/10-21", "aaacccgggttt"); |
267 | 1 | SequenceI seq1proxy = new SequenceDummy("Seq1"); |
268 | ||
269 | // map to region within sequence is ok | |
270 | 1 | assertTrue(AlignedCodonFrame.couldRealiseSequence(seq1proxy, seq1, 12, |
271 | 17)); | |
272 | // map to region overlapping sequence is ok | |
273 | 1 | assertTrue( |
274 | AlignedCodonFrame.couldRealiseSequence(seq1proxy, seq1, 5, 10)); | |
275 | 1 | assertTrue(AlignedCodonFrame.couldRealiseSequence(seq1proxy, seq1, 21, |
276 | 26)); | |
277 | // map to region before sequence is not ok | |
278 | 1 | assertFalse( |
279 | AlignedCodonFrame.couldRealiseSequence(seq1proxy, seq1, 4, 9)); | |
280 | // map to region after sequence is not ok | |
281 | 1 | assertFalse(AlignedCodonFrame.couldRealiseSequence(seq1proxy, seq1, 22, |
282 | 27)); | |
283 | ||
284 | /* | |
285 | * test should fail if name doesn't match | |
286 | */ | |
287 | 1 | seq1proxy.setName("Seq1a"); |
288 | 1 | assertFalse(AlignedCodonFrame.couldRealiseSequence(seq1proxy, seq1, 12, |
289 | 17)); | |
290 | 1 | seq1proxy.setName("Seq1"); |
291 | 1 | seq1.setName("Seq1a"); |
292 | 1 | assertFalse(AlignedCodonFrame.couldRealiseSequence(seq1proxy, seq1, 12, |
293 | 17)); | |
294 | ||
295 | /* | |
296 | * a dummy sequence can't replace a real one | |
297 | */ | |
298 | 1 | assertFalse(AlignedCodonFrame.couldRealiseSequence(seq1, seq1proxy, 12, |
299 | 17)); | |
300 | ||
301 | /* | |
302 | * a dummy sequence can't replace a dummy sequence | |
303 | */ | |
304 | 1 | SequenceI seq1proxy2 = new SequenceDummy("Seq1"); |
305 | 1 | assertFalse(AlignedCodonFrame.couldRealiseSequence(seq1proxy, |
306 | seq1proxy2, 12, 17)); | |
307 | ||
308 | /* | |
309 | * a real sequence can't replace a real one | |
310 | */ | |
311 | 1 | SequenceI seq1a = new Sequence("Seq1/10-21", "aaacccgggttt"); |
312 | 1 | assertFalse( |
313 | AlignedCodonFrame.couldRealiseSequence(seq1, seq1a, 12, 17)); | |
314 | } | |
315 | ||
316 | /** | |
317 | * Tests for the method that tests whether any mapping to a dummy sequence can | |
318 | * be 'realised' to a given real sequence | |
319 | */ | |
320 | 1 | @Test(groups = { "Functional" }) |
321 | public void testIsRealisableWith() | |
322 | { | |
323 | 1 | SequenceI seq1 = new Sequence("Seq1", "tttaaaCCCGGGtttaaa"); |
324 | 1 | SequenceI seq2 = new Sequence("Seq2", "PG"); |
325 | 1 | SequenceI seq1proxy = new SequenceDummy("Seq1"); |
326 | 1 | seq1.createDatasetSequence(); |
327 | 1 | seq2.createDatasetSequence(); |
328 | 1 | MapList mapList = new MapList(new int[] { 7, 12 }, new int[] { 2, 3 }, |
329 | 3, 1); | |
330 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
331 | 1 | acf.addMap(seq1proxy, seq2, mapList); |
332 | ||
333 | /* | |
334 | * Seq2 is mapped to SequenceDummy seq1proxy bases 4-9 | |
335 | * This is 'realisable' from real sequence Seq1 | |
336 | */ | |
337 | 1 | assertTrue(acf.isRealisableWith(seq1)); |
338 | ||
339 | /* | |
340 | * test should fail if name doesn't match | |
341 | */ | |
342 | 1 | seq1proxy.setName("Seq1a"); |
343 | 1 | assertFalse(acf.isRealisableWith(seq1)); |
344 | 1 | seq1proxy.setName("Seq1"); |
345 | ||
346 | 1 | SequenceI seq1ds = seq1.getDatasetSequence(); |
347 | 1 | seq1ds.setName("Seq1a"); |
348 | 1 | assertFalse(acf.isRealisableWith(seq1)); |
349 | 1 | seq1ds.setName("Seq1"); |
350 | ||
351 | /* | |
352 | * test should fail if no sequence overlap with mapping of bases 7-12 | |
353 | * use artificial start/end values to test this | |
354 | */ | |
355 | 1 | seq1ds.setStart(1); |
356 | 1 | seq1ds.setEnd(6); |
357 | // seq1 precedes mapped region: | |
358 | 1 | assertFalse(acf.isRealisableWith(seq1)); |
359 | 1 | seq1ds.setEnd(7); |
360 | // seq1 includes first mapped base: | |
361 | 1 | assertTrue(acf.isRealisableWith(seq1)); |
362 | 1 | seq1ds.setStart(13); |
363 | 1 | seq1ds.setEnd(18); |
364 | // seq1 follows mapped region: | |
365 | 1 | assertFalse(acf.isRealisableWith(seq1)); |
366 | 1 | seq1ds.setStart(12); |
367 | // seq1 includes last mapped base: | |
368 | 1 | assertTrue(acf.isRealisableWith(seq1)); |
369 | } | |
370 | ||
371 | /** | |
372 | * Tests for the method that converts mappings to a dummy sequence to mappings | |
373 | * to a compatible real sequence | |
374 | */ | |
375 | 1 | @Test(groups = { "Functional" }) |
376 | public void testRealiseWith() | |
377 | { | |
378 | 1 | SequenceI seq1 = new Sequence("Seq1", "tttCAACCCGGGtttaaa"); |
379 | 1 | SequenceI seq2 = new Sequence("Seq2", "QPG"); |
380 | 1 | SequenceI seq2a = new Sequence("Seq2a", "QPG"); |
381 | 1 | SequenceI seq1proxy = new SequenceDummy("Seq1"); |
382 | 1 | seq1.createDatasetSequence(); |
383 | 1 | seq2.createDatasetSequence(); |
384 | 1 | seq2a.createDatasetSequence(); |
385 | ||
386 | /* | |
387 | * Make mappings from Seq2 and Seq2a peptides to dummy sequence Seq1 | |
388 | */ | |
389 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
390 | ||
391 | // map PG to codons 7-12 (CCCGGG) | |
392 | 1 | MapList mapping1 = new MapList(new int[] { 7, 12 }, new int[] { 2, 3 }, |
393 | 3, 1); | |
394 | 1 | acf.addMap(seq1proxy, seq2, mapping1); |
395 | 1 | acf.addMap(seq1proxy, seq2a, mapping1); |
396 | ||
397 | // map QP to codons 4-9 (CAACCC) | |
398 | 1 | MapList mapping2 = new MapList(new int[] { 4, 9 }, new int[] { 1, 2 }, |
399 | 3, 1); | |
400 | 1 | acf.addMap(seq1proxy, seq2, mapping2); |
401 | 1 | acf.addMap(seq1proxy, seq2a, mapping2); |
402 | ||
403 | /* | |
404 | * acf now has two mappings one from Seq1 to Seq2, one from Seq1 to Seq2a | |
405 | */ | |
406 | 1 | assertEquals(2, acf.getdnaSeqs().length); |
407 | 1 | assertSame(seq1proxy, acf.getdnaSeqs()[0]); |
408 | 1 | assertSame(seq1proxy, acf.getdnaSeqs()[1]); |
409 | 1 | assertEquals(2, acf.getProtMappings().length); |
410 | ||
411 | // 'realise' these mappings with the compatible sequence seq1 | |
412 | // two mappings should be updated: | |
413 | 1 | assertEquals(2, acf.realiseWith(seq1)); |
414 | 1 | assertSame(seq1.getDatasetSequence(), acf.getdnaSeqs()[0]); |
415 | 1 | assertSame(seq1.getDatasetSequence(), acf.getdnaSeqs()[1]); |
416 | } | |
417 | ||
418 | /** | |
419 | * Test the method that locates the mapped codon for a protein position. | |
420 | */ | |
421 | 1 | @Test(groups = { "Functional" }) |
422 | public void testGetMappedRegion_eitherWay() | |
423 | { | |
424 | 1 | final Sequence seq1 = new Sequence("Seq1", "AAACCCGGGTTT"); |
425 | 1 | seq1.createDatasetSequence(); |
426 | 1 | final Sequence seq2 = new Sequence("Seq2", "KPGF"); |
427 | 1 | seq2.createDatasetSequence(); |
428 | 1 | final Sequence seq3 = new Sequence("Seq3", "QYKPGFSW"); |
429 | 1 | seq3.createDatasetSequence(); |
430 | ||
431 | /* | |
432 | * map Seq1 to all of Seq2 and part of Seq3 | |
433 | */ | |
434 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
435 | 1 | MapList map = new MapList(new int[] { 1, 12 }, new int[] { 1, 4 }, 3, |
436 | 1); | |
437 | 1 | acf.addMap(seq1.getDatasetSequence(), seq2.getDatasetSequence(), map); |
438 | 1 | map = new MapList(new int[] { 1, 12 }, new int[] { 3, 6 }, 3, 1); |
439 | 1 | acf.addMap(seq1.getDatasetSequence(), seq3.getDatasetSequence(), map); |
440 | ||
441 | /* | |
442 | * map part of Seq3 to Seq2 | |
443 | */ | |
444 | 1 | map = new MapList(new int[] { 3, 6 }, new int[] { 1, 4 }, 1, 1); |
445 | 1 | acf.addMap(seq3.getDatasetSequence(), seq2.getDatasetSequence(), map); |
446 | ||
447 | /* | |
448 | * original case - locate mapped codon for protein position | |
449 | */ | |
450 | 1 | assertArrayEquals(new int[] { 4, 6 }, |
451 | acf.getMappedRegion(seq1, seq2, 2)); | |
452 | 1 | assertArrayEquals(new int[] { 7, 9 }, |
453 | acf.getMappedRegion(seq1, seq3, 5)); | |
454 | 1 | assertNull(acf.getMappedRegion(seq1, seq3, 1)); |
455 | ||
456 | /* | |
457 | * locate mapped protein for protein position | |
458 | */ | |
459 | 1 | assertArrayEquals(new int[] { 4, 4 }, |
460 | acf.getMappedRegion(seq3, seq2, 2)); | |
461 | ||
462 | /* | |
463 | * reverse location protein-to-protein | |
464 | */ | |
465 | 1 | assertArrayEquals(new int[] { 2, 2 }, |
466 | acf.getMappedRegion(seq2, seq3, 4)); | |
467 | ||
468 | /* | |
469 | * reverse location protein-from-nucleotide | |
470 | * any of codon [4, 5, 6] positions map to seq2/2 | |
471 | */ | |
472 | 1 | assertArrayEquals(new int[] { 2, 2 }, |
473 | acf.getMappedRegion(seq2, seq1, 4)); | |
474 | 1 | assertArrayEquals(new int[] { 2, 2 }, |
475 | acf.getMappedRegion(seq2, seq1, 5)); | |
476 | 1 | assertArrayEquals(new int[] { 2, 2 }, |
477 | acf.getMappedRegion(seq2, seq1, 6)); | |
478 | } | |
479 | ||
480 | /** | |
481 | * Tests for addMap. See also tests for MapList.addMapList | |
482 | */ | |
483 | 1 | @Test(groups = { "Functional" }) |
484 | public void testAddMap() | |
485 | { | |
486 | 1 | final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T"); |
487 | 1 | seq1.createDatasetSequence(); |
488 | 1 | final Sequence aseq1 = new Sequence("Seq1", "-V-L"); |
489 | 1 | aseq1.createDatasetSequence(); |
490 | ||
491 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
492 | 1 | MapList map = new MapList(new int[] { 2, 4, 6, 6, 8, 9 }, |
493 | new int[] | |
494 | { 1, 2 }, 3, 1); | |
495 | 1 | acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map); |
496 | 1 | assertEquals(1, acf.getMappingsFromSequence(seq1).size()); |
497 | 1 | Mapping before = acf.getMappingsFromSequence(seq1).get(0); |
498 | ||
499 | /* | |
500 | * add the same map again, verify it doesn't get duplicated | |
501 | */ | |
502 | 1 | acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map); |
503 | 1 | assertEquals(1, acf.getMappingsFromSequence(seq1).size()); |
504 | 1 | assertSame(before, acf.getMappingsFromSequence(seq1).get(0)); |
505 | } | |
506 | ||
507 | 1 | @Test(groups = { "Functional" }) |
508 | public void testGetCoveringMapping() | |
509 | { | |
510 | 1 | SequenceI dna = new Sequence("dna", "acttcaATGGCGGACtaattt"); |
511 | 1 | SequenceI cds = new Sequence("cds/7-15", "ATGGCGGAC"); |
512 | 1 | cds.setDatasetSequence(dna); |
513 | 1 | SequenceI pep = new Sequence("pep", "MAD"); |
514 | ||
515 | /* | |
516 | * with null argument or no mappings | |
517 | */ | |
518 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
519 | 1 | assertNull(acf.getCoveringMapping(null, null)); |
520 | 1 | assertNull(acf.getCoveringMapping(dna, null)); |
521 | 1 | assertNull(acf.getCoveringMapping(null, pep)); |
522 | 1 | assertNull(acf.getCoveringMapping(dna, pep)); |
523 | ||
524 | /* | |
525 | * with a non-covering mapping e.g. overlapping exon | |
526 | */ | |
527 | 1 | MapList map = new MapList(new int[] { 7, 9 }, new int[] { 1, 1 }, 3, 1); |
528 | 1 | acf.addMap(dna, pep, map); |
529 | 1 | assertNull(acf.getCoveringMapping(dna, pep)); |
530 | ||
531 | 1 | acf = new AlignedCodonFrame(); |
532 | 1 | MapList map2 = new MapList(new int[] { 13, 18 }, new int[] { 2, 2 }, 3, |
533 | 1); | |
534 | 1 | acf.addMap(dna, pep, map2); |
535 | 1 | assertNull(acf.getCoveringMapping(dna, pep)); |
536 | ||
537 | /* | |
538 | * with a covering mapping from CDS (dataset) to protein | |
539 | */ | |
540 | 1 | acf = new AlignedCodonFrame(); |
541 | 1 | MapList map3 = new MapList(new int[] { 7, 15 }, new int[] { 1, 3 }, 3, |
542 | 1); | |
543 | 1 | acf.addMap(dna, pep, map3); |
544 | 1 | assertNull(acf.getCoveringMapping(dna, pep)); |
545 | 1 | SequenceToSequenceMapping mapping = acf.getCoveringMapping(cds, pep); |
546 | 1 | assertNotNull(mapping); |
547 | ||
548 | /* | |
549 | * with a mapping that extends to stop codon | |
550 | */ | |
551 | 1 | acf = new AlignedCodonFrame(); |
552 | 1 | MapList map4 = new MapList(new int[] { 7, 18 }, new int[] { 1, 3 }, 3, |
553 | 1); | |
554 | 1 | acf.addMap(dna, pep, map4); |
555 | 1 | assertNull(acf.getCoveringMapping(dna, pep)); |
556 | 1 | assertNull(acf.getCoveringMapping(cds, pep)); |
557 | 1 | SequenceI cds2 = new Sequence("cds/7-18", "ATGGCGGACtaa"); |
558 | 1 | cds2.setDatasetSequence(dna); |
559 | 1 | mapping = acf.getCoveringMapping(cds2, pep); |
560 | 1 | assertNotNull(mapping); |
561 | } | |
562 | ||
563 | /** | |
564 | * Test the method that adds mapped positions to SearchResults | |
565 | */ | |
566 | 1 | @Test(groups = { "Functional" }) |
567 | public void testMarkMappedRegion() | |
568 | { | |
569 | // introns lower case, exons upper case | |
570 | 1 | final Sequence dna1 = new Sequence("Seq1/10-18", "c-G-TA-gC-gT-T"); |
571 | 1 | dna1.createDatasetSequence(); |
572 | 1 | final Sequence dna2 = new Sequence("Seq2/20-28", "-TA-gG-Gg-CG-a"); |
573 | 1 | dna2.createDatasetSequence(); |
574 | ||
575 | 1 | final Sequence pep1 = new Sequence("Seq1/3-4", "-P-R"); |
576 | 1 | pep1.createDatasetSequence(); |
577 | 1 | final Sequence pep2 = new Sequence("Seq2/7-9", "-LY-Q"); |
578 | 1 | pep2.createDatasetSequence(); |
579 | ||
580 | /* | |
581 | * First with no mappings | |
582 | */ | |
583 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
584 | 1 | SearchResults sr = new SearchResults(); |
585 | 1 | acf.markMappedRegion(dna1, 12, sr); |
586 | 1 | assertTrue(sr.isEmpty()); |
587 | ||
588 | /* | |
589 | * Set up the mappings for the exons (upper-case bases) | |
590 | * Note residue Q is unmapped | |
591 | */ | |
592 | 1 | MapList map1 = new MapList(new int[] { 11, 13, 15, 15, 17, 18 }, |
593 | new int[] | |
594 | { 3, 4 }, 3, 1); | |
595 | 1 | acf.addMap(dna1.getDatasetSequence(), pep1.getDatasetSequence(), map1); |
596 | 1 | MapList map2 = new MapList(new int[] { 20, 21, 23, 24, 26, 27 }, |
597 | new int[] | |
598 | { 7, 8 }, 3, 1); | |
599 | 1 | acf.addMap(dna2.getDatasetSequence(), pep2.getDatasetSequence(), map2); |
600 | ||
601 | /* | |
602 | * intron bases are not mapped | |
603 | */ | |
604 | 1 | acf.markMappedRegion(dna1, 10, sr); |
605 | 1 | assertTrue(sr.isEmpty()); |
606 | ||
607 | /* | |
608 | * Q is not mapped | |
609 | */ | |
610 | 1 | acf.markMappedRegion(pep2, 9, sr); |
611 | 1 | assertTrue(sr.isEmpty()); |
612 | ||
613 | /* | |
614 | * mark peptide position for exon position (of aligned sequence) | |
615 | */ | |
616 | 1 | acf.markMappedRegion(dna1, 11, sr); |
617 | 1 | SearchResults expected = new SearchResults(); |
618 | 1 | expected.addResult(pep1.getDatasetSequence(), 3, 3); |
619 | 1 | assertEquals(sr, expected); |
620 | ||
621 | /* | |
622 | * mark peptide position for exon position of dataset sequence - same result | |
623 | */ | |
624 | 1 | sr = new SearchResults(); |
625 | 1 | acf.markMappedRegion(dna1.getDatasetSequence(), 11, sr); |
626 | 1 | assertEquals(sr, expected); |
627 | ||
628 | /* | |
629 | * marking the same position a second time should not create a duplicate match | |
630 | */ | |
631 | 1 | acf.markMappedRegion(dna1.getDatasetSequence(), 12, sr); |
632 | 1 | assertEquals(sr, expected); |
633 | ||
634 | /* | |
635 | * mark exon positions for peptide position (of aligned sequence) | |
636 | */ | |
637 | 1 | sr = new SearchResults(); |
638 | 1 | acf.markMappedRegion(pep2, 7, sr); // codon positions 20, 21, 23 |
639 | 1 | expected = new SearchResults(); |
640 | 1 | expected.addResult(dna2.getDatasetSequence(), 20, 21); |
641 | 1 | expected.addResult(dna2.getDatasetSequence(), 23, 23); |
642 | 1 | assertEquals(sr, expected); |
643 | ||
644 | /* | |
645 | * add another codon to the same SearchResults | |
646 | */ | |
647 | 1 | acf.markMappedRegion(pep1.getDatasetSequence(), 4, sr); // codon positions |
648 | // 15, 17, 18 | |
649 | 1 | expected.addResult(dna1.getDatasetSequence(), 15, 15); |
650 | 1 | expected.addResult(dna1.getDatasetSequence(), 17, 18); |
651 | 1 | assertEquals(sr, expected); |
652 | } | |
653 | ||
654 | 1 | @Test(groups = { "Functional" }) |
655 | public void testGetCoveringCodonMapping() | |
656 | { | |
657 | 1 | SequenceI dna = new Sequence("dna/10-30", "acttcaATGGCGGACtaattt"); |
658 | // CDS sequence with its own dataset sequence (JAL-3763) | |
659 | 1 | SequenceI cds = new Sequence("cds/1-9", "-A--TGGC-GGAC"); |
660 | 1 | cds.createDatasetSequence(); |
661 | 1 | SequenceI pep = new Sequence("pep/1-3", "MAD"); |
662 | ||
663 | /* | |
664 | * with null argument or no mappings | |
665 | */ | |
666 | 1 | AlignedCodonFrame acf = new AlignedCodonFrame(); |
667 | 1 | assertNull(acf.getCoveringCodonMapping(null)); |
668 | 1 | assertNull(acf.getCoveringCodonMapping(dna)); |
669 | 1 | assertNull(acf.getCoveringCodonMapping(pep)); |
670 | ||
671 | /* | |
672 | * with a non-covering mapping e.g. overlapping exon | |
673 | */ | |
674 | 1 | MapList map = new MapList(new int[] { 16, 18 }, new int[] { 1, 1 }, 3, |
675 | 1); | |
676 | 1 | acf.addMap(dna, pep, map); |
677 | 1 | assertNull(acf.getCoveringCodonMapping(dna)); |
678 | 1 | assertNull(acf.getCoveringCodonMapping(pep)); |
679 | ||
680 | 1 | acf = new AlignedCodonFrame(); |
681 | 1 | MapList map2 = new MapList(new int[] { 13, 18 }, new int[] { 2, 2 }, 3, |
682 | 1); | |
683 | 1 | acf.addMap(dna, pep, map2); |
684 | 1 | assertNull(acf.getCoveringCodonMapping(dna)); |
685 | 1 | assertNull(acf.getCoveringCodonMapping(pep)); |
686 | ||
687 | /* | |
688 | * with a covering mapping from CDS (dataset) to protein | |
689 | */ | |
690 | 1 | acf = new AlignedCodonFrame(); |
691 | 1 | MapList map3 = new MapList(new int[] { 1, 9 }, new int[] { 1, 3 }, 3, |
692 | 1); | |
693 | 1 | acf.addMap(cds.getDatasetSequence(), pep, map3); |
694 | 1 | assertNull(acf.getCoveringCodonMapping(dna)); |
695 | 1 | SequenceToSequenceMapping mapping = acf.getCoveringCodonMapping(pep); |
696 | 1 | assertNotNull(mapping); |
697 | 1 | SequenceToSequenceMapping mapping2 = acf |
698 | .getCoveringCodonMapping(cds.getDatasetSequence()); | |
699 | 1 | assertSame(mapping, mapping2); |
700 | ||
701 | /* | |
702 | * with a mapping that extends to stop codon | |
703 | * (EMBL CDS location often includes the stop codon) | |
704 | * - getCoveringCodonMapping is lenient (doesn't require exact length match) | |
705 | */ | |
706 | 1 | SequenceI cds2 = new Sequence("cds/1-12", "-A--TGGC-GGACTAA"); |
707 | 1 | cds2.createDatasetSequence(); |
708 | 1 | acf = new AlignedCodonFrame(); |
709 | 1 | MapList map4 = new MapList(new int[] { 1, 12 }, new int[] { 1, 3 }, 3, |
710 | 1); | |
711 | 1 | acf.addMap(cds2, pep, map4); |
712 | 1 | mapping = acf.getCoveringCodonMapping(cds2.getDatasetSequence()); |
713 | 1 | assertNotNull(mapping); |
714 | 1 | mapping2 = acf.getCoveringCodonMapping(pep); |
715 | 1 | assertSame(mapping, mapping2); |
716 | } | |
717 | } |