JAL-653 JAL-1968 FeaturesFile now handles Jalview or GFF2 or GFF3
[jalview.git] / test / jalview / io / FeaturesFileTest.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;
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.assertTrue;
27
28 import jalview.datamodel.AlignmentI;
29 import jalview.datamodel.SequenceFeature;
30 import jalview.gui.AlignFrame;
31 import jalview.schemes.AnnotationColourGradient;
32 import jalview.schemes.GraduatedColor;
33
34 import java.awt.Color;
35 import java.io.File;
36 import java.io.IOException;
37 import java.util.Map;
38
39 import org.testng.annotations.Test;
40
41 public class FeaturesFileTest
42 {
43
44   @Test(groups = { "Functional" })
45   public void testParse() throws Exception
46   {
47     File f = new File("examples/uniref50.fa");
48     AlignmentI al = readAlignmentFile(f);
49     AlignFrame af = new AlignFrame(al, 500, 500);
50     Map<String, Object> colours = af.getFeatureRenderer()
51             .getFeatureColours();
52     FeaturesFile featuresFile = new FeaturesFile(
53             "examples/exampleFeatures.txt", FormatAdapter.FILE);
54     assertTrue("Test " + "Features file test"
55             + "\nFailed to parse features file.",
56             featuresFile.parse(al.getDataset(), colours, true));
57
58     /*
59      * Refetch the colour map from the FeatureRenderer (to confirm it has been
60      * updated - JAL-1904), and verify (some) feature group colours
61      */
62     colours = af.getFeatureRenderer().getFeatureColours();
63     assertEquals("26 feature group colours not found", 26, colours.size());
64     assertEquals(colours.get("Cath"), new Color(0x93b1d1));
65     assertEquals(colours.get("ASX-MOTIF"), new Color(0x6addbb));
66
67     /*
68      * verify (some) features on sequences
69      */
70     SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
71             .getSequenceFeatures(); // FER_CAPAA
72     assertEquals(7, sfs.length);
73     SequenceFeature sf = sfs[0];
74     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
75     assertEquals(39, sf.begin);
76     assertEquals(39, sf.end);
77     assertEquals("uniprot", sf.featureGroup);
78     assertEquals("METAL", sf.type);
79     sf = sfs[1];
80     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
81     assertEquals(44, sf.begin);
82     assertEquals(44, sf.end);
83     assertEquals("uniprot", sf.featureGroup);
84     assertEquals("METAL", sf.type);
85     sf = sfs[2];
86     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
87     assertEquals(47, sf.begin);
88     assertEquals(47, sf.end);
89     assertEquals("uniprot", sf.featureGroup);
90     assertEquals("METAL", sf.type);
91     sf = sfs[3];
92     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
93     assertEquals(77, sf.begin);
94     assertEquals(77, sf.end);
95     assertEquals("uniprot", sf.featureGroup);
96     assertEquals("METAL", sf.type);
97     sf = sfs[4];
98     assertEquals("Fer2 Status: True Positive Pfam 8_8%LINK%",
99             sf.description);
100     assertEquals("Pfam 8_8|http://pfam.sanger.ac.uk/family/PF00111",
101             sf.links.get(0).toString());
102     assertEquals(8, sf.begin);
103     assertEquals(83, sf.end);
104     assertEquals("uniprot", sf.featureGroup);
105     assertEquals("Pfam", sf.type);
106     sf = sfs[5];
107     assertEquals("Ferredoxin_fold Status: True Positive ", sf.description);
108     assertEquals(3, sf.begin);
109     assertEquals(93, sf.end);
110     assertEquals("uniprot", sf.featureGroup);
111     assertEquals("Cath", sf.type);
112     sf = sfs[6];
113     assertEquals(
114             "High confidence server. Only hits with scores over 0.8 are reported. PHOSPHORYLATION (T) 89_8%LINK%",
115             sf.description);
116     assertEquals(
117             "PHOSPHORYLATION (T) 89_8|http://www.cbs.dtu.dk/cgi-bin/proview/webface-link?seqid=P83527&amp;service=NetPhos-2.0",
118             sf.links.get(0).toString());
119     assertEquals(89, sf.begin);
120     assertEquals(89, sf.end);
121     assertEquals("netphos", sf.featureGroup);
122     assertEquals("PHOSPHORYLATION (T)", sf.type);
123   }
124
125   /**
126    * Test parsing a features file with a mix of Jalview and GFF formatted
127    * content
128    * 
129    * @throws Exception
130    */
131   @Test(groups = { "Functional" })
132   public void testParse_mixedJalviewGff() throws Exception
133   {
134     File f = new File("examples/uniref50.fa");
135     AlignmentI al = readAlignmentFile(f);
136     AlignFrame af = new AlignFrame(al, 500, 500);
137     Map<String, Object> colours = af.getFeatureRenderer()
138             .getFeatureColours();
139     String gffData = "METAL\tcc9900\n" + "GFF\n"
140             + "FER_CAPAA\tuniprot\tMETAL\t44\t45\t4.0\t.\t.\n"
141             + "FER1_SOLLC\tuniprot\tPfam\t55\t130\t2.0\t.\t.";
142     FeaturesFile featuresFile = new FeaturesFile(gffData,
143             FormatAdapter.PASTE);
144     assertTrue("Failed to parse features file",
145             featuresFile.parse(al.getDataset(), colours, true));
146
147     // verify colours read or synthesized
148     colours = af.getFeatureRenderer().getFeatureColours();
149     assertEquals("1 feature group colours not found", 1, colours.size());
150     assertEquals(colours.get("METAL"), new Color(0xcc9900));
151
152     // verify feature on FER_CAPAA
153     SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
154             .getSequenceFeatures();
155     assertEquals(1, sfs.length);
156     SequenceFeature sf = sfs[0];
157     assertEquals("uniprot", sf.description);
158     assertEquals(44, sf.begin);
159     assertEquals(45, sf.end);
160     assertEquals("uniprot", sf.featureGroup);
161     assertEquals("METAL", sf.type);
162     assertEquals(4f, sf.getScore(), 0.001f);
163
164     // verify feature on FER1_SOLLC
165     sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
166     assertEquals(1, sfs.length);
167     sf = sfs[0];
168     assertEquals("uniprot", sf.description);
169     assertEquals(55, sf.begin);
170     assertEquals(130, sf.end);
171     assertEquals("uniprot", sf.featureGroup);
172     assertEquals("Pfam", sf.type);
173     assertEquals(2f, sf.getScore(), 0.001f);
174   }
175
176   public static AlignmentI readAlignmentFile(File f) throws IOException
177   {
178     System.out.println("Reading file: " + f);
179     String ff = f.getPath();
180     FormatAdapter rf = new FormatAdapter();
181
182     AlignmentI al = rf.readFile(ff, FormatAdapter.FILE,
183             new IdentifyFile().identify(ff, FormatAdapter.FILE));
184
185     al.setDataset(null); // creates dataset sequences
186     assertNotNull("Couldn't read supplied alignment data.", al);
187     return al;
188   }
189
190   /**
191    * Test various ways of describing a feature colour scheme
192    * 
193    * @throws Exception
194    */
195   @Test(groups = { "Functional" })
196   public void testParseGraduatedColourScheme() throws Exception
197   {
198     FeaturesFile ff = new FeaturesFile();
199
200     // colour by label:
201     GraduatedColor gc = ff.parseGraduatedColourScheme(
202             "BETA-TURN-IR\t9a6a94", "label");
203     assertTrue(gc.isColourByLabel());
204     assertEquals(Color.white, gc.getMinColor());
205     assertEquals(Color.black, gc.getMaxColor());
206     assertTrue(gc.isAutoScale());
207
208     // using colour name, rgb, etc:
209     String spec = "blue|255,0,255|absolute|20.0|95.0|below|66.0";
210     gc = ff.parseGraduatedColourScheme("BETA-TURN-IR\t" + spec, spec);
211     assertFalse(gc.isColourByLabel());
212     assertEquals(Color.blue, gc.getMinColor());
213     assertEquals(new Color(255, 0, 255), gc.getMaxColor());
214     assertFalse(gc.isAutoScale());
215     assertFalse(gc.getTolow());
216     assertEquals(20.0f, gc.getMin(), 0.001f);
217     assertEquals(95.0f, gc.getMax(), 0.001f);
218     assertEquals(AnnotationColourGradient.BELOW_THRESHOLD,
219             gc.getThreshType());
220     assertEquals(66.0f, gc.getThresh(), 0.001f);
221
222     // inverse gradient high to low:
223     spec = "blue|255,0,255|95.0|20.0|below|66.0";
224     gc = ff.parseGraduatedColourScheme("BETA-TURN-IR\t" + spec, spec);
225     assertTrue(gc.isAutoScale());
226     assertTrue(gc.getTolow());
227   }
228
229   /**
230    * Test parsing a features file with GFF formatted content only
231    * 
232    * @throws Exception
233    */
234   @Test(groups = { "Functional" })
235   public void testParse_pureGff() throws Exception
236   {
237     File f = new File("examples/uniref50.fa");
238     AlignmentI al = readAlignmentFile(f);
239     AlignFrame af = new AlignFrame(al, 500, 500);
240     Map<String, Object> colours = af.getFeatureRenderer()
241             .getFeatureColours();
242     String gffData = "##gff-version 2\n"
243             + "FER_CAPAA\tuniprot\tMETAL\t39\t39\t0.0\t.\t.\t"
244             + "Note=Iron-sulfur (2Fe-2S);Note=another note;evidence=ECO:0000255|PROSITE-ProRule:PRU00465\n"
245             + "FER1_SOLLC\tuniprot\tPfam\t55\t130\t3.0\t.\t.";
246     FeaturesFile featuresFile = new FeaturesFile(gffData,
247             FormatAdapter.PASTE);
248     assertTrue("Failed to parse features file",
249             featuresFile.parse(al.getDataset(), colours, true));
250
251     // verify feature on FER_CAPAA
252     SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
253             .getSequenceFeatures();
254     assertEquals(1, sfs.length);
255     SequenceFeature sf = sfs[0];
256     // description parsed from Note attribute
257     assertEquals("Iron-sulfur (2Fe-2S); another note", sf.description);
258     assertEquals(39, sf.begin);
259     assertEquals(39, sf.end);
260     assertEquals("uniprot", sf.featureGroup);
261     assertEquals("METAL", sf.type);
262     assertEquals(
263             "Note=Iron-sulfur (2Fe-2S);Note=another note;evidence=ECO:0000255|PROSITE-ProRule:PRU00465",
264             sf.getValue("ATTRIBUTES"));
265
266     // verify feature on FER1_SOLLC1
267     sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
268     assertEquals(1, sfs.length);
269     sf = sfs[0];
270     assertEquals("uniprot", sf.description);
271     assertEquals(55, sf.begin);
272     assertEquals(130, sf.end);
273     assertEquals("uniprot", sf.featureGroup);
274     assertEquals("Pfam", sf.type);
275     assertEquals(3f, sf.getScore(), 0.001f);
276   }
277
278   /**
279    * Test parsing a features file with Jalview format features (but no colour
280    * descriptors or startgroup to give the hint not to parse as GFF)
281    * 
282    * @throws Exception
283    */
284   @Test(groups = { "Functional" })
285   public void testParse_jalviewFeaturesOnly() throws Exception
286   {
287     File f = new File("examples/uniref50.fa");
288     AlignmentI al = readAlignmentFile(f);
289     AlignFrame af = new AlignFrame(al, 500, 500);
290     Map<String, Object> colours = af.getFeatureRenderer()
291             .getFeatureColours();
292
293     /*
294      * one feature on FER_CAPAA and one on sequence 3 (index 2) FER1_SOLLC
295      */
296     String featureData = "Iron-sulfur (2Fe-2S)\tFER_CAPAA\t-1\t39\t39\tMETAL\n"
297             + "Iron-phosphorus (2Fe-P)\tID_NOT_SPECIFIED\t2\t86\t87\tMETALLIC\n";
298     FeaturesFile featuresFile = new FeaturesFile(featureData,
299             FormatAdapter.PASTE);
300     assertTrue("Failed to parse features file",
301             featuresFile.parse(al.getDataset(), colours, true));
302
303     // verify FER_CAPAA feature
304     SequenceFeature[] sfs = al.getSequenceAt(0).getDatasetSequence()
305             .getSequenceFeatures();
306     assertEquals(1, sfs.length);
307     SequenceFeature sf = sfs[0];
308     assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
309     assertEquals(39, sf.begin);
310     assertEquals(39, sf.end);
311     assertEquals("METAL", sf.type);
312
313     // verify FER1_SOLLC feature
314     sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
315     assertEquals(1, sfs.length);
316     sf = sfs[0];
317     assertEquals("Iron-phosphorus (2Fe-P)", sf.description);
318     assertEquals(86, sf.begin);
319     assertEquals(87, sf.end);
320     assertEquals("METALLIC", sf.type);
321   }
322 }