JAL-3438 spotless for 2.11.2.0
[jalview.git] / test / jalview / io / gff / ExonerateHelperTest.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.io.gff;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertNull;
25 import static org.testng.AssertJUnit.assertSame;
26 import static org.testng.AssertJUnit.assertTrue;
27 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
28
29 import jalview.datamodel.AlignedCodonFrame;
30 import jalview.datamodel.Alignment;
31 import jalview.datamodel.AlignmentI;
32 import jalview.datamodel.Mapping;
33 import jalview.datamodel.MappingType;
34 import jalview.datamodel.Sequence;
35 import jalview.datamodel.SequenceDummy;
36 import jalview.datamodel.SequenceI;
37 import jalview.gui.AlignFrame;
38 import jalview.gui.JvOptionPane;
39 import jalview.io.DataSourceType;
40 import jalview.io.FileLoader;
41
42 import java.io.IOException;
43 import java.util.ArrayList;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47
48 import org.testng.annotations.BeforeClass;
49 import org.testng.annotations.Test;
50
51 public class ExonerateHelperTest
52 {
53
54   @BeforeClass(alwaysRun = true)
55   public void setUpJvOptionPane()
56   {
57     JvOptionPane.setInteractiveMode(false);
58     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
59   }
60
61   @Test(groups = "Functional")
62   public void testGetMappingType()
63   {
64     // protein-to-dna:
65     assertSame(MappingType.PeptideToNucleotide, ExonerateHelper
66             .getMappingType("exonerate:protein2genome:local"));
67     assertSame(MappingType.PeptideToNucleotide,
68             ExonerateHelper.getMappingType("exonerate:protein2dna:local"));
69
70     // dna-to-dna:
71     assertSame(MappingType.NucleotideToNucleotide,
72             ExonerateHelper.getMappingType("coding2coding"));
73     assertSame(MappingType.NucleotideToNucleotide,
74             ExonerateHelper.getMappingType("coding2genome"));
75     assertSame(MappingType.NucleotideToNucleotide,
76             ExonerateHelper.getMappingType("cdna2genome"));
77     assertSame(MappingType.NucleotideToNucleotide,
78             ExonerateHelper.getMappingType("genome2genome"));
79     assertNull(ExonerateHelper.getMappingType("affine:local"));
80   }
81
82   /**
83    * Test processing one exonerate GFF line for the case where the mapping is
84    * protein2dna, similarity feature is on the query (the protein), match to the
85    * forward strand, target sequence is in neither the alignment nor the 'new
86    * sequences'
87    * 
88    * @throws IOException
89    */
90   @Test(groups = "Functional")
91   public void testProcessGffSimilarity_protein2dna_forward_querygff()
92           throws IOException
93   {
94     ExonerateHelper testee = new ExonerateHelper();
95     List<SequenceI> newseqs = new ArrayList<SequenceI>();
96     String[] gff = "Seq\texonerate:protein2dna:local\tsimilarity\t3\t10\t.\t+\t.\talignment_id 0 ; Target dna1 ; Align 3 400 8"
97             .split("\\t");
98     SequenceI seq = new Sequence("Seq", "PQRASTGKEEDVMIWCHQN");
99     seq.createDatasetSequence();
100     AlignmentI align = new Alignment(new SequenceI[] {});
101     Map<String, List<String>> set = Gff2Helper.parseNameValuePairs(gff[8]);
102
103     /*
104      * this should create a mapping from Seq2/3-10 to virtual sequence
105      * dna1 (added to newseqs) positions 400-423
106      */
107     testee.processGffSimilarity(set, seq, gff, align, newseqs, false);
108     assertEquals(1, newseqs.size());
109     assertTrue(newseqs.get(0) instanceof SequenceDummy);
110     assertEquals("dna1", newseqs.get(0).getName());
111     assertEquals(1, align.getCodonFrames().size());
112     AlignedCodonFrame mapping = align.getCodonFrames().iterator().next();
113     assertEquals(1, mapping.getAaSeqs().length);
114     assertSame(seq.getDatasetSequence(), mapping.getAaSeqs()[0]);
115     assertEquals(1, mapping.getdnaSeqs().length);
116     assertSame(newseqs.get(0), mapping.getdnaSeqs()[0]);
117     assertEquals(1, mapping.getdnaToProt().length);
118     assertEquals(1, mapping.getdnaToProt()[0].getFromRanges().size());
119     assertArrayEquals(new int[] { 400, 423 },
120             mapping.getdnaToProt()[0].getFromRanges().get(0));
121     assertEquals(1, mapping.getdnaToProt()[0].getToRanges().size());
122     assertArrayEquals(new int[] { 3, 10 },
123             mapping.getdnaToProt()[0].getToRanges().get(0));
124   }
125
126   /**
127    * Test processing one exonerate GFF line for the case where the mapping is
128    * protein2dna, similarity feature is on the query (the protein), match to the
129    * reverse strand
130    * 
131    * @throws IOException
132    */
133   @Test(groups = "Functional")
134   public void testProcessGffSimilarity_protein2dna_reverse_querygff()
135           throws IOException
136   {
137     ExonerateHelper testee = new ExonerateHelper();
138     List<SequenceI> newseqs = new ArrayList<SequenceI>();
139     String[] gff = "Seq\texonerate:protein2dna:local\tsimilarity\t3\t10\t0\t-\t.\talignment_id 0 ; Target dna1 ; Align 3 400 8"
140             .split("\\t");
141     SequenceI seq = new Sequence("Seq", "PQRASTGKEEDVMIWCHQN");
142     seq.createDatasetSequence();
143     AlignmentI align = new Alignment(new SequenceI[] {});
144     Map<String, List<String>> set = Gff2Helper.parseNameValuePairs(gff[8]);
145
146     /*
147      * this should create a mapping from Seq2/3-10 to virtual sequence
148      * dna1 (added to newseqs) positions 400-377 (reverse)
149      */
150     testee.processGffSimilarity(set, seq, gff, align, newseqs, false);
151     assertEquals(1, newseqs.size());
152     assertTrue(newseqs.get(0) instanceof SequenceDummy);
153     assertEquals("dna1", newseqs.get(0).getName());
154     assertEquals(1, align.getCodonFrames().size());
155     AlignedCodonFrame mapping = align.getCodonFrames().iterator().next();
156     assertEquals(1, mapping.getAaSeqs().length);
157     assertSame(seq.getDatasetSequence(), mapping.getAaSeqs()[0]);
158     assertEquals(1, mapping.getdnaSeqs().length);
159     assertSame(newseqs.get(0), mapping.getdnaSeqs()[0]);
160     assertEquals(1, mapping.getdnaToProt().length);
161     assertEquals(1, mapping.getdnaToProt()[0].getFromRanges().size());
162     assertArrayEquals(new int[] { 400, 377 },
163             mapping.getdnaToProt()[0].getFromRanges().get(0));
164     assertEquals(1, mapping.getdnaToProt()[0].getToRanges().size());
165     assertArrayEquals(new int[] { 3, 10 },
166             mapping.getdnaToProt()[0].getToRanges().get(0));
167   }
168
169   /**
170    * Test processing one exonerate GFF line for the case where the mapping is
171    * protein2dna, similarity feature is on the target (the dna), match to the
172    * forward strand
173    * 
174    * @throws IOException
175    */
176   @Test(groups = "Functional")
177   public void testProcessGffSimilarity_protein2dna_forward_targetgff()
178           throws IOException
179   {
180     ExonerateHelper testee = new ExonerateHelper();
181     List<SequenceI> newseqs = new ArrayList<SequenceI>();
182     String[] gff = "dna1\texonerate:protein2dna:local\tsimilarity\t400\t423\t0\t+\t.\talignment_id 0 ; Query Prot1 ; Align 400 3 24"
183             .split("\\t");
184     SequenceI seq = new Sequence("dna1/391-430",
185             "CGATCCGATCCGATCCGATCCGATCCGATCCGATCCGATC");
186     seq.createDatasetSequence();
187     AlignmentI align = new Alignment(new SequenceI[] { seq });
188     // GFF feature on the target describes mapping from base 400 for
189     // count 24 to position 3
190     Map<String, List<String>> set = Gff2Helper.parseNameValuePairs(gff[8]);
191
192     /*
193      * this should create a mapping from virtual sequence dna1 (added to 
194      * newseqs) positions 400-423 to Prot1/3-10
195      */
196     testee.processGffSimilarity(set, seq, gff, align, newseqs, false);
197     assertEquals(1, newseqs.size());
198     assertTrue(newseqs.get(0) instanceof SequenceDummy);
199     assertEquals("Prot1", newseqs.get(0).getName());
200     assertEquals(1, align.getCodonFrames().size());
201     AlignedCodonFrame mapping = align.getCodonFrames().iterator().next();
202     assertEquals(1, mapping.getAaSeqs().length);
203     assertSame(newseqs.get(0), mapping.getAaSeqs()[0]);
204     assertSame(seq.getDatasetSequence(), mapping.getdnaSeqs()[0]);
205     assertEquals(1, mapping.getdnaSeqs().length);
206     assertEquals(1, mapping.getdnaToProt().length);
207     assertEquals(1, mapping.getdnaToProt()[0].getFromRanges().size());
208     assertArrayEquals(new int[] { 400, 423 },
209             mapping.getdnaToProt()[0].getFromRanges().get(0));
210     assertEquals(1, mapping.getdnaToProt()[0].getToRanges().size());
211     assertArrayEquals(new int[] { 3, 10 },
212             mapping.getdnaToProt()[0].getToRanges().get(0));
213   }
214
215   /**
216    * Test processing one exonerate GFF line for the case where the mapping is
217    * protein2dna, similarity feature is on the target (the dna), match to the
218    * reverse strand
219    * 
220    * @throws IOException
221    */
222   @Test(groups = "Functional")
223   public void testProcessGffSimilarity_protein2dna_reverse_targetgff()
224           throws IOException
225   {
226     ExonerateHelper testee = new ExonerateHelper();
227     List<SequenceI> newseqs = new ArrayList<SequenceI>();
228     String[] gff = "dna1\texonerate:protein2dna:local\tsimilarity\t377\t400\t0\t-\t.\talignment_id 0 ; Query Prot1 ; Align 400 3 24"
229             .split("\\t");
230     SequenceI seq = new Sequence("dna1/371-410",
231             "CGATCCGATCCGATCCGATCCGATCCGATCCGATCCGATC");
232     seq.createDatasetSequence();
233     AlignmentI align = new Alignment(new SequenceI[] { seq });
234     // GFF feature on the target describes mapping from base 400 for
235     // count 24 to position 3
236     Map<String, List<String>> set = Gff2Helper.parseNameValuePairs(gff[8]);
237
238     /*
239      * this should create a mapping from virtual sequence dna1 (added to 
240      * newseqs) positions 400-377 (reverse) to Prot1/3-10
241      */
242     testee.processGffSimilarity(set, seq, gff, align, newseqs, false);
243     assertEquals(1, newseqs.size());
244     assertTrue(newseqs.get(0) instanceof SequenceDummy);
245     assertEquals("Prot1", newseqs.get(0).getName());
246     assertEquals(1, align.getCodonFrames().size());
247     AlignedCodonFrame mapping = align.getCodonFrames().iterator().next();
248     assertEquals(1, mapping.getAaSeqs().length);
249     assertSame(newseqs.get(0), mapping.getAaSeqs()[0]);
250     assertSame(seq.getDatasetSequence(), mapping.getdnaSeqs()[0]);
251     assertEquals(1, mapping.getdnaSeqs().length);
252     assertEquals(1, mapping.getdnaToProt().length);
253     assertEquals(1, mapping.getdnaToProt()[0].getFromRanges().size());
254     assertArrayEquals(new int[] { 400, 377 },
255             mapping.getdnaToProt()[0].getFromRanges().get(0));
256     assertEquals(1, mapping.getdnaToProt()[0].getToRanges().size());
257     assertArrayEquals(new int[] { 3, 10 },
258             mapping.getdnaToProt()[0].getToRanges().get(0));
259   }
260
261   /**
262    * Tests loading exonerate GFF2 output, including 'similarity' alignment
263    * feature, on to sequences
264    */
265   @Test(groups = { "Functional" })
266   public void testAddExonerateGffToAlignment()
267   {
268     FileLoader loader = new FileLoader(false);
269     AlignFrame af = loader.LoadFileWaitTillLoaded(
270             "examples/testdata/exonerateseqs.fa", DataSourceType.FILE);
271
272     af.loadJalviewDataFile("examples/testdata/exonerateoutput.gff",
273             DataSourceType.FILE, null, null);
274
275     /*
276      * verify one mapping to a dummy sequence, one to a real one
277      */
278     List<AlignedCodonFrame> mappings = af.getViewport().getAlignment()
279             .getDataset().getCodonFrames();
280     assertEquals(2, mappings.size());
281     Iterator<AlignedCodonFrame> iter = mappings.iterator();
282
283     // first mapping is to dummy sequence
284     AlignedCodonFrame mapping = iter.next();
285     Mapping[] mapList = mapping.getProtMappings();
286     assertEquals(1, mapList.length);
287     assertTrue(mapList[0].getTo() instanceof SequenceDummy);
288     assertEquals("DDB_G0269124", mapList[0].getTo().getName());
289
290     // 143 in protein should map to codon [11270, 11269, 11268] in dna
291     int[] mappedRegion = mapList[0].getMap().locateInFrom(143, 143);
292     assertArrayEquals(new int[] { 11270, 11268 }, mappedRegion);
293
294     // second mapping is to a sequence in the alignment
295     mapping = iter.next();
296     mapList = mapping.getProtMappings();
297     assertEquals(1, mapList.length);
298     SequenceI proteinSeq = af.getViewport().getAlignment()
299             .findName("DDB_G0280897");
300     assertSame(proteinSeq.getDatasetSequence(), mapList[0].getTo());
301     assertEquals(1, mapping.getdnaToProt().length);
302
303     // 143 in protein should map to codon [11270, 11269, 11268] in dna
304     mappedRegion = mapList[0].getMap().locateInFrom(143, 143);
305     assertArrayEquals(new int[] { 11270, 11268 }, mappedRegion);
306
307     // 182 in protein should map to codon [11153, 11152, 11151] in dna
308     mappedRegion = mapList[0].getMap().locateInFrom(182, 182);
309     assertArrayEquals(new int[] { 11153, 11151 }, mappedRegion);
310
311     // and the reverse mapping:
312     mappedRegion = mapList[0].getMap().locateInTo(11151, 11153);
313     assertArrayEquals(new int[] { 182, 182 }, mappedRegion);
314
315     // 11150 in dna should _not_ map to protein
316     mappedRegion = mapList[0].getMap().locateInTo(11150, 11150);
317     assertNull(mappedRegion);
318
319     // similarly 183 in protein should _not_ map to dna
320     mappedRegion = mapList[0].getMap().locateInFrom(183, 183);
321     assertNull(mappedRegion);
322   }
323 }