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