JAL-653 code tidy / tests for 'realise gff mappings'
[jalview.git] / test / jalview / datamodel / AlignedCodonFrameTest.java
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.assertNull;
26 import static org.testng.AssertJUnit.assertSame;
27 import static org.testng.AssertJUnit.assertTrue;
28
29 import jalview.util.MapList;
30
31 import java.util.Arrays;
32
33 import org.testng.annotations.Test;
34
35 public class AlignedCodonFrameTest
36 {
37
38   /**
39    * Test the method that locates the first aligned sequence that has a mapping.
40    */
41   @Test(groups = { "Functional" })
42   public void testFindAlignedSequence()
43   {
44     AlignmentI cdna = new Alignment(new SequenceI[] {});
45     final Sequence seq1 = new Sequence("Seq1", "C-G-TA-GC");
46     seq1.createDatasetSequence();
47     cdna.addSequence(seq1);
48     final Sequence seq2 = new Sequence("Seq2", "-TA-GG-GG");
49     seq2.createDatasetSequence();
50     cdna.addSequence(seq2);
51
52     AlignmentI aa = new Alignment(new SequenceI[] {});
53     final Sequence aseq1 = new Sequence("Seq1", "-P-R");
54     aseq1.createDatasetSequence();
55     aa.addSequence(aseq1);
56     final Sequence aseq2 = new Sequence("Seq2", "-LY-");
57     aseq2.createDatasetSequence();
58     aa.addSequence(aseq2);
59
60     /*
61      * Mapping from first DNA sequence to second AA sequence.
62      */
63     AlignedCodonFrame acf = new AlignedCodonFrame();
64
65     assertNull(acf.findAlignedSequence(seq1, aa));
66
67     MapList map = new MapList(new int[] { 1, 6 }, new int[] { 1, 2 }, 3, 1);
68     acf.addMap(seq1.getDatasetSequence(), aseq2.getDatasetSequence(), map);
69
70     /*
71      * DNA seq1 maps to AA seq2
72      */
73     assertEquals(aa.getSequenceAt(1), acf.findAlignedSequence(cdna
74             .getSequenceAt(0).getDatasetSequence(), aa));
75
76     assertEquals(cdna.getSequenceAt(0), acf.findAlignedSequence(aa
77             .getSequenceAt(1).getDatasetSequence(), cdna));
78   }
79
80   /**
81    * Test the method that locates the mapped codon for a protein position.
82    */
83   @Test(groups = { "Functional" })
84   public void testGetMappedRegion()
85   {
86     // introns lower case, exons upper case
87     final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T");
88     seq1.createDatasetSequence();
89     final Sequence seq2 = new Sequence("Seq2", "-TA-gG-Gg-CG-a");
90     seq2.createDatasetSequence();
91
92     final Sequence aseq1 = new Sequence("Seq1", "-P-R");
93     aseq1.createDatasetSequence();
94     final Sequence aseq2 = new Sequence("Seq2", "-LY-");
95     aseq2.createDatasetSequence();
96
97     /*
98      * First with no mappings
99      */
100     AlignedCodonFrame acf = new AlignedCodonFrame();
101
102     assertNull(acf.getMappedRegion(seq1, aseq1, 1));
103
104     /*
105      * Set up the mappings for the exons (upper-case bases)
106      */
107     MapList map = new MapList(new int[] { 2, 4, 6, 6, 8, 9 }, new int[] {
108         1, 2 }, 3, 1);
109     acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
110     map = new MapList(new int[] { 1, 2, 4, 5, 7, 8 }, new int[] { 1, 2 },
111             3, 1);
112     acf.addMap(seq2.getDatasetSequence(), aseq2.getDatasetSequence(), map);
113
114     assertEquals("[2, 4]",
115             Arrays.toString(acf.getMappedRegion(seq1, aseq1, 1)));
116     assertEquals("[6, 6, 8, 9]",
117             Arrays.toString(acf.getMappedRegion(seq1, aseq1, 2)));
118     assertEquals("[1, 2, 4, 4]",
119             Arrays.toString(acf.getMappedRegion(seq2, aseq2, 1)));
120     assertEquals("[5, 5, 7, 8]",
121             Arrays.toString(acf.getMappedRegion(seq2, aseq2, 2)));
122
123     /*
124      * No mapping from sequence 1 to sequence 2
125      */
126     assertNull(acf.getMappedRegion(seq1, aseq2, 1));
127   }
128
129   @Test(groups = { "Functional" })
130   public void testGetMappedCodon()
131   {
132     final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T");
133     seq1.createDatasetSequence();
134     final Sequence aseq1 = new Sequence("Seq1", "-P-R");
135     aseq1.createDatasetSequence();
136
137     /*
138      * First with no mappings
139      */
140     AlignedCodonFrame acf = new AlignedCodonFrame();
141
142     assertNull(acf.getMappedCodon(seq1.getDatasetSequence(), 0));
143
144     /*
145      * Set up the mappings for the exons (upper-case bases)
146      */
147     MapList map = new MapList(new int[] { 2, 4, 6, 6, 8, 9 }, new int[] {
148         1, 2 }, 3, 1);
149     acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
150
151     assertEquals("[G, T, A]", Arrays.toString(acf.getMappedCodon(
152             aseq1.getDatasetSequence(), 1)));
153     assertEquals("[C, T, T]", Arrays.toString(acf.getMappedCodon(
154             aseq1.getDatasetSequence(), 2)));
155   }
156
157   /**
158    * Test for the case where sequences have start > 1
159    */
160   @Test(groups = { "Functional" })
161   public void testGetMappedCodon_forSubSequences()
162   {
163     final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T", 27, 35);
164     seq1.createDatasetSequence();
165
166     final Sequence aseq1 = new Sequence("Seq1", "-P-R", 12, 13);
167     aseq1.createDatasetSequence();
168
169     /*
170      * Set up the mappings for the exons (upper-case bases)
171      */
172     AlignedCodonFrame acf = new AlignedCodonFrame();
173     MapList map = new MapList(new int[] { 28, 30, 32, 32, 34, 35 },
174             new int[] { 12, 13 }, 3, 1);
175     acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
176
177     assertEquals("[G, T, A]", Arrays.toString(acf.getMappedCodon(
178             aseq1.getDatasetSequence(), 12)));
179     assertEquals("[C, T, T]", Arrays.toString(acf.getMappedCodon(
180             aseq1.getDatasetSequence(), 13)));
181   }
182
183   @Test(groups = { "Functional" })
184   public void testCouldReplaceSequence()
185   {
186     SequenceI seq1 = new Sequence("Seq1/10-21", "aaacccgggttt");
187     SequenceI seq2 = new Sequence("Seq2", "PG");
188     SequenceI seq1proxy = new SequenceDummy("Seq1");
189
190     // map to region within sequence is ok
191     assertTrue(AlignedCodonFrame.couldReplaceSequence(seq1proxy, seq1, 12,
192             17));
193     // map to region overlapping sequence is ok
194     assertTrue(AlignedCodonFrame.couldReplaceSequence(seq1proxy, seq1, 5,
195             10));
196     assertTrue(AlignedCodonFrame.couldReplaceSequence(seq1proxy, seq1, 21,
197             26));
198     // map to region before sequence is not ok
199     assertFalse(AlignedCodonFrame.couldReplaceSequence(seq1proxy, seq1, 4,
200             9));
201     // map to region after sequence is not ok
202     assertFalse(AlignedCodonFrame.couldReplaceSequence(seq1proxy, seq1, 22,
203             27));
204
205     /*
206      * test should fail if name doesn't match
207      */
208     seq1proxy.setName("Seq1a");
209     assertFalse(AlignedCodonFrame.couldReplaceSequence(seq1proxy, seq1, 12,
210             17));
211     seq1proxy.setName("Seq1");
212     seq1.setName("Seq1a");
213     assertFalse(AlignedCodonFrame.couldReplaceSequence(seq1proxy, seq1, 12,
214             17));
215   }
216
217   /**
218    * Tests for the method that tests whether any mapping to a dummy sequence can
219    * be 'realised' to a given real sequence
220    */
221   @Test(groups = { "Functional" })
222   public void testIsRealisableWith()
223   {
224     SequenceI seq1 = new Sequence("Seq1", "tttaaaCCCGGGtttaaa");
225     SequenceI seq2 = new Sequence("Seq2", "PG");
226     SequenceI seq1proxy = new SequenceDummy("Seq1");
227     seq1.createDatasetSequence();
228     seq2.createDatasetSequence();
229     MapList mapList = new MapList(new int[] { 7, 12 }, new int[] { 2, 3 },
230             3, 1);
231     AlignedCodonFrame acf = new AlignedCodonFrame();
232     acf.addMap(seq1proxy, seq2, mapList);
233
234     /*
235      * Seq2 is mapped to SequenceDummy seq1proxy bases 4-9
236      * This is 'realisable' from real sequence Seq1
237      */
238     assertTrue(acf.isRealisableWith(seq1));
239
240     /*
241      * test should fail if name doesn't match
242      */
243     seq1proxy.setName("Seq1a");
244     assertFalse(acf.isRealisableWith(seq1));
245     seq1proxy.setName("Seq1");
246
247     SequenceI seq1ds = seq1.getDatasetSequence();
248     seq1ds.setName("Seq1a");
249     assertFalse(acf.isRealisableWith(seq1));
250     seq1ds.setName("Seq1");
251
252     /*
253      * test should fail if no sequence overlap with mapping of bases 7-12
254      * use artificial start/end values to test this
255      */
256     seq1ds.setStart(1);
257     seq1ds.setEnd(6);
258     // seq1 precedes mapped region:
259     assertFalse(acf.isRealisableWith(seq1));
260     seq1ds.setEnd(7);
261     // seq1 includes first mapped base:
262     assertTrue(acf.isRealisableWith(seq1));
263     seq1ds.setStart(13);
264     seq1ds.setEnd(18);
265     // seq1 follows mapped region:
266     assertFalse(acf.isRealisableWith(seq1));
267     seq1ds.setStart(12);
268     // seq1 includes last mapped base:
269     assertTrue(acf.isRealisableWith(seq1));
270   }
271
272   /**
273    * Tests for the method that converts mappings to a dummy sequence to mappings
274    * to a compatible real sequence
275    */
276   @Test(groups = { "Functional" })
277   public void testRealiseWith()
278   {
279     SequenceI seq1 = new Sequence("Seq1", "tttCAACCCGGGtttaaa");
280     SequenceI seq2 = new Sequence("Seq2", "QPG");
281     SequenceI seq1proxy = new SequenceDummy("Seq1");
282     seq1.createDatasetSequence();
283     seq2.createDatasetSequence();
284
285     /*
286      * Make two mappings from Seq2 peptide to dummy sequence Seq1
287      */
288     AlignedCodonFrame acf = new AlignedCodonFrame();
289
290     // map PG to codons 7-12 (CCCGGG)
291     MapList mapping1 = new MapList(new int[] { 7, 12 }, new int[] { 2, 3 },
292             3, 1);
293     acf.addMap(seq1proxy, seq2, mapping1);
294
295     // map QP to codons 4-9 (CAACCC)
296     MapList mapping2 = new MapList(new int[] { 4, 9 }, new int[] { 1, 2 },
297             3, 1);
298     acf.addMap(seq1proxy, seq2, mapping2);
299
300     assertEquals(2, acf.getdnaSeqs().length);
301     assertSame(seq1proxy, acf.getdnaSeqs()[0]);
302     assertSame(seq1proxy, acf.getdnaSeqs()[1]);
303     assertEquals(2, acf.getProtMappings().length);
304
305     // 'realise' these mappings with the compatible sequence seq1
306     // two mappings should be updated:
307     assertEquals(2, acf.realiseWith(seq1));
308     assertSame(seq1.getDatasetSequence(), acf.getdnaSeqs()[0]);
309     assertSame(seq1.getDatasetSequence(), acf.getdnaSeqs()[1]);
310   }
311 }