Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.io

File FeaturesFileTest.java

 

Code metrics

2
308
16
1
710
528
17
0.06
19.25
16
1.06

Classes

Class Line # Actions
FeaturesFileTest 63 308 17 1
0.996932599.7%
 

Contributing tests

This file is covered by 12 tests. .

Source view

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.assertSame;
27    import static org.testng.AssertJUnit.assertTrue;
28    import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
29   
30    import jalview.api.FeatureColourI;
31    import jalview.api.FeatureRenderer;
32    import jalview.datamodel.Alignment;
33    import jalview.datamodel.AlignmentI;
34    import jalview.datamodel.SequenceDummy;
35    import jalview.datamodel.SequenceFeature;
36    import jalview.datamodel.SequenceI;
37    import jalview.datamodel.features.FeatureMatcher;
38    import jalview.datamodel.features.FeatureMatcherI;
39    import jalview.datamodel.features.FeatureMatcherSet;
40    import jalview.datamodel.features.FeatureMatcherSetI;
41    import jalview.datamodel.features.SequenceFeatures;
42    import jalview.gui.AlignFrame;
43    import jalview.gui.Desktop;
44    import jalview.gui.JvOptionPane;
45    import jalview.schemes.FeatureColour;
46    import jalview.structure.StructureSelectionManager;
47    import jalview.util.matcher.Condition;
48   
49    import java.awt.Color;
50    import java.io.File;
51    import java.io.IOException;
52    import java.util.ArrayList;
53    import java.util.Arrays;
54    import java.util.HashMap;
55    import java.util.Iterator;
56    import java.util.List;
57    import java.util.Map;
58   
59    import org.testng.annotations.AfterClass;
60    import org.testng.annotations.BeforeClass;
61    import org.testng.annotations.Test;
62   
 
63    public class FeaturesFileTest
64    {
65    private static String simpleGffFile = "examples/testdata/simpleGff3.gff";
66   
 
67  1 toggle @AfterClass(alwaysRun = true)
68    public void tearDownAfterClass()
69    {
70    /*
71    * remove any sequence mappings created so they don't pollute other tests
72    */
73  1 StructureSelectionManager ssm = StructureSelectionManager
74    .getStructureSelectionManager(Desktop.instance);
75  1 ssm.resetAll();
76    }
77   
 
78  1 toggle @BeforeClass(alwaysRun = true)
79    public void setUpJvOptionPane()
80    {
81  1 JvOptionPane.setInteractiveMode(false);
82  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
83    }
84   
 
85  1 toggle @Test(groups = { "Functional" })
86    public void testParse() throws Exception
87    {
88  1 File f = new File("examples/uniref50.fa");
89  1 AlignmentI al = readAlignmentFile(f);
90  1 AlignFrame af = new AlignFrame(al, 500, 500);
91  1 Map<String, FeatureColourI> colours = af.getFeatureRenderer()
92    .getFeatureColours();
93  1 FeaturesFile featuresFile = new FeaturesFile(
94    "examples/exampleFeatures.txt", DataSourceType.FILE);
95  1 assertTrue("Test " + "Features file test"
96    + "\nFailed to parse features file.",
97    featuresFile.parse(al.getDataset(), colours, true));
98   
99    /*
100    * Refetch the colour map from the FeatureRenderer (to confirm it has been
101    * updated - JAL-1904), and verify (some) feature group colours
102    */
103  1 colours = af.getFeatureRenderer().getFeatureColours();
104  1 assertEquals("27 feature group colours not found", 27, colours.size());
105  1 assertEquals(colours.get("Cath").getColour(), new Color(0x93b1d1));
106  1 assertEquals(colours.get("ASX-MOTIF").getColour(), new Color(0x6addbb));
107  1 FeatureColourI kdColour = colours.get("kdHydrophobicity");
108  1 assertTrue(kdColour.isGraduatedColour());
109  1 assertTrue(kdColour.isAboveThreshold());
110  1 assertEquals(-2f, kdColour.getThreshold());
111   
112    /*
113    * verify (some) features on sequences
114    */
115  1 List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
116    .getSequenceFeatures(); // FER_CAPAA
117  1 SequenceFeatures.sortFeatures(sfs, true);
118  1 assertEquals(8, sfs.size());
119   
120    /*
121    * verify (in ascending start position order)
122    */
123  1 SequenceFeature sf = sfs.get(0);
124  1 assertEquals("Pfam family%LINK%", sf.description);
125  1 assertEquals(0, sf.begin);
126  1 assertEquals(0, sf.end);
127  1 assertEquals("uniprot", sf.featureGroup);
128  1 assertEquals("Pfam", sf.type);
129  1 assertEquals(1, sf.links.size());
130  1 assertEquals("Pfam family|http://pfam.xfam.org/family/PF00111",
131    sf.links.get(0));
132   
133  1 sf = sfs.get(1);
134  1 assertEquals("Ferredoxin_fold Status: True Positive ", sf.description);
135  1 assertEquals(3, sf.begin);
136  1 assertEquals(93, sf.end);
137  1 assertEquals("uniprot", sf.featureGroup);
138  1 assertEquals("Cath", sf.type);
139   
140  1 sf = sfs.get(2);
141  1 assertEquals("Fer2 Status: True Positive Pfam 8_8%LINK%",
142    sf.description);
143  1 assertEquals("Pfam 8_8|http://pfam.xfam.org/family/PF00111",
144    sf.links.get(0));
145  1 assertEquals(8, sf.begin);
146  1 assertEquals(83, sf.end);
147  1 assertEquals("uniprot", sf.featureGroup);
148  1 assertEquals("Pfam", sf.type);
149   
150  1 sf = sfs.get(3);
151  1 assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
152  1 assertEquals(39, sf.begin);
153  1 assertEquals(39, sf.end);
154  1 assertEquals("uniprot", sf.featureGroup);
155  1 assertEquals("METAL", sf.type);
156   
157  1 sf = sfs.get(4);
158  1 assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
159  1 assertEquals(44, sf.begin);
160  1 assertEquals(44, sf.end);
161  1 assertEquals("uniprot", sf.featureGroup);
162  1 assertEquals("METAL", sf.type);
163   
164  1 sf = sfs.get(5);
165  1 assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
166  1 assertEquals(47, sf.begin);
167  1 assertEquals(47, sf.end);
168  1 assertEquals("uniprot", sf.featureGroup);
169  1 assertEquals("METAL", sf.type);
170   
171  1 sf = sfs.get(6);
172  1 assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
173  1 assertEquals(77, sf.begin);
174  1 assertEquals(77, sf.end);
175  1 assertEquals("uniprot", sf.featureGroup);
176  1 assertEquals("METAL", sf.type);
177   
178  1 sf = sfs.get(7);
179  1 assertEquals(
180    "High confidence server. Only hits with scores over 0.8 are reported. PHOSPHORYLATION (T) 89_8%LINK%",
181    sf.description);
182  1 assertEquals(
183    "PHOSPHORYLATION (T) 89_8|http://www.cbs.dtu.dk/cgi-bin/proview/webface-link?seqid=P83527&amp;service=NetPhos-2.0",
184    sf.links.get(0));
185  1 assertEquals(89, sf.begin);
186  1 assertEquals(89, sf.end);
187  1 assertEquals("netphos", sf.featureGroup);
188  1 assertEquals("PHOSPHORYLATION (T)", sf.type);
189    }
190   
191    /**
192    * Test parsing a features file with a mix of Jalview and GFF formatted
193    * content
194    *
195    * @throws Exception
196    */
 
197  1 toggle @Test(groups = { "Functional" })
198    public void testParse_mixedJalviewGff() throws Exception
199    {
200  1 File f = new File("examples/uniref50.fa");
201  1 AlignmentI al = readAlignmentFile(f);
202  1 AlignFrame af = new AlignFrame(al, 500, 500);
203  1 Map<String, FeatureColourI> colours = af.getFeatureRenderer()
204    .getFeatureColours();
205    // GFF2 uses space as name/value separator in column 9
206  1 String gffData = "METAL\tcc9900\n"
207    + "GFF\n"
208    + "FER_CAPAA\tuniprot\tMETAL\t44\t45\t4.0\t.\t.\tNote Iron-sulfur; Note 2Fe-2S\n"
209    + "FER1_SOLLC\tuniprot\tPfam\t55\t130\t2.0\t.\t.";
210  1 FeaturesFile featuresFile = new FeaturesFile(gffData,
211    DataSourceType.PASTE);
212  1 assertTrue("Failed to parse features file",
213    featuresFile.parse(al.getDataset(), colours, true));
214   
215    // verify colours read or synthesized
216  1 colours = af.getFeatureRenderer().getFeatureColours();
217  1 assertEquals("1 feature group colours not found", 1, colours.size());
218  1 assertEquals(colours.get("METAL").getColour(), new Color(0xcc9900));
219   
220    // verify feature on FER_CAPAA
221  1 List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
222    .getSequenceFeatures();
223  1 assertEquals(1, sfs.size());
224  1 SequenceFeature sf = sfs.get(0);
225  1 assertEquals("Iron-sulfur,2Fe-2S", sf.description);
226  1 assertEquals(44, sf.begin);
227  1 assertEquals(45, sf.end);
228  1 assertEquals("uniprot", sf.featureGroup);
229  1 assertEquals("METAL", sf.type);
230  1 assertEquals(4f, sf.getScore(), 0.001f);
231   
232    // verify feature on FER1_SOLLC
233  1 sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
234  1 assertEquals(1, sfs.size());
235  1 sf = sfs.get(0);
236  1 assertEquals("uniprot", sf.description);
237  1 assertEquals(55, sf.begin);
238  1 assertEquals(130, sf.end);
239  1 assertEquals("uniprot", sf.featureGroup);
240  1 assertEquals("Pfam", sf.type);
241  1 assertEquals(2f, sf.getScore(), 0.001f);
242    }
243   
 
244  6 toggle public static AlignmentI readAlignmentFile(File f) throws IOException
245    {
246  6 System.out.println("Reading file: " + f);
247  6 String ff = f.getPath();
248  6 FormatAdapter rf = new FormatAdapter();
249   
250  6 AlignmentI al = rf.readFile(ff, DataSourceType.FILE,
251    new IdentifyFile().identify(ff, DataSourceType.FILE));
252   
253  6 al.setDataset(null); // creates dataset sequences
254  6 assertNotNull("Couldn't read supplied alignment data.", al);
255  6 return al;
256    }
257   
258    /**
259    * Test parsing a features file with GFF formatted content only
260    *
261    * @throws Exception
262    */
 
263  1 toggle @Test(groups = { "Functional" })
264    public void testParse_pureGff3() throws Exception
265    {
266  1 File f = new File("examples/uniref50.fa");
267  1 AlignmentI al = readAlignmentFile(f);
268  1 AlignFrame af = new AlignFrame(al, 500, 500);
269  1 Map<String, FeatureColourI> colours = af.getFeatureRenderer()
270    .getFeatureColours();
271    // GFF3 uses '=' separator for name/value pairs in colum 9
272  1 String gffData = "##gff-version 3\n"
273    + "FER_CAPAA\tuniprot\tMETAL\t39\t39\t0.0\t.\t.\t"
274    + "Note=Iron-sulfur (2Fe-2S);Note=another note;evidence=ECO:0000255|PROSITE-ProRule:PRU00465\n"
275    + "FER1_SOLLC\tuniprot\tPfam\t55\t130\t3.0\t.\t.\tID=$23";
276  1 FeaturesFile featuresFile = new FeaturesFile(gffData,
277    DataSourceType.PASTE);
278  1 assertTrue("Failed to parse features file",
279    featuresFile.parse(al.getDataset(), colours, true));
280   
281    // verify feature on FER_CAPAA
282  1 List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
283    .getSequenceFeatures();
284  1 assertEquals(1, sfs.size());
285  1 SequenceFeature sf = sfs.get(0);
286    // description parsed from Note attribute
287  1 assertEquals("Iron-sulfur (2Fe-2S),another note", sf.description);
288  1 assertEquals(39, sf.begin);
289  1 assertEquals(39, sf.end);
290  1 assertEquals("uniprot", sf.featureGroup);
291  1 assertEquals("METAL", sf.type);
292  1 assertEquals(
293    "Note=Iron-sulfur (2Fe-2S);Note=another note;evidence=ECO:0000255|PROSITE-ProRule:PRU00465",
294    sf.getValue("ATTRIBUTES"));
295   
296    // verify feature on FER1_SOLLC1
297  1 sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
298  1 assertEquals(1, sfs.size());
299  1 sf = sfs.get(0);
300    // ID used for description if available
301  1 assertEquals("$23", sf.description);
302  1 assertEquals(55, sf.begin);
303  1 assertEquals(130, sf.end);
304  1 assertEquals("uniprot", sf.featureGroup);
305  1 assertEquals("Pfam", sf.type);
306  1 assertEquals(3f, sf.getScore(), 0.001f);
307    }
308   
309    /**
310    * Test parsing a features file with Jalview format features (but no colour
311    * descriptors or startgroup to give the hint not to parse as GFF)
312    *
313    * @throws Exception
314    */
 
315  1 toggle @Test(groups = { "Functional" })
316    public void testParse_jalviewFeaturesOnly() throws Exception
317    {
318  1 File f = new File("examples/uniref50.fa");
319  1 AlignmentI al = readAlignmentFile(f);
320  1 AlignFrame af = new AlignFrame(al, 500, 500);
321  1 Map<String, FeatureColourI> colours = af.getFeatureRenderer()
322    .getFeatureColours();
323   
324    /*
325    * one feature on FER_CAPAA and one on sequence 3 (index 2) FER1_SOLLC
326    */
327  1 String featureData = "Iron-sulfur (2Fe-2S)\tFER_CAPAA\t-1\t39\t39\tMETAL\n"
328    + "Iron-phosphorus (2Fe-P)\tID_NOT_SPECIFIED\t2\t86\t87\tMETALLIC\n";
329  1 FeaturesFile featuresFile = new FeaturesFile(featureData,
330    DataSourceType.PASTE);
331  1 assertTrue("Failed to parse features file",
332    featuresFile.parse(al.getDataset(), colours, true));
333   
334    // verify FER_CAPAA feature
335  1 List<SequenceFeature> sfs = al.getSequenceAt(0).getDatasetSequence()
336    .getSequenceFeatures();
337  1 assertEquals(1, sfs.size());
338  1 SequenceFeature sf = sfs.get(0);
339  1 assertEquals("Iron-sulfur (2Fe-2S)", sf.description);
340  1 assertEquals(39, sf.begin);
341  1 assertEquals(39, sf.end);
342  1 assertEquals("METAL", sf.type);
343   
344    // verify FER1_SOLLC feature
345  1 sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
346  1 assertEquals(1, sfs.size());
347  1 sf = sfs.get(0);
348  1 assertEquals("Iron-phosphorus (2Fe-P)", sf.description);
349  1 assertEquals(86, sf.begin);
350  1 assertEquals(87, sf.end);
351  1 assertEquals("METALLIC", sf.type);
352    }
353   
 
354  4 toggle private void checkDatasetfromSimpleGff3(AlignmentI dataset)
355    {
356  4 assertEquals("no sequences extracted from GFF3 file", 2,
357    dataset.getHeight());
358   
359  4 SequenceI seq1 = dataset.findName("seq1");
360  4 SequenceI seq2 = dataset.findName("seq2");
361  4 assertNotNull(seq1);
362  4 assertNotNull(seq2);
363  4 assertFalse(
364    "Failed to replace dummy seq1 with real sequence",
365    seq1 instanceof SequenceDummy
366    && ((SequenceDummy) seq1).isDummy());
367  4 assertFalse(
368    "Failed to replace dummy seq2 with real sequence",
369    seq2 instanceof SequenceDummy
370    && ((SequenceDummy) seq2).isDummy());
371  4 String placeholderseq = new SequenceDummy("foo").getSequenceAsString();
372  4 assertFalse("dummy replacement buggy for seq1",
373    placeholderseq.equals(seq1.getSequenceAsString()));
374  4 assertFalse("dummy replacement buggy for seq2",
375    placeholderseq.equals(seq2.getSequenceAsString()));
376  4 assertNotNull("No features added to seq1", seq1.getSequenceFeatures());
377  4 assertEquals("Wrong number of features", 3, seq1.getSequenceFeatures()
378    .size());
379  4 assertTrue(seq2.getSequenceFeatures().isEmpty());
380  4 assertEquals(
381    "Wrong number of features",
382    0,
383  4 seq2.getSequenceFeatures() == null ? 0 : seq2
384    .getSequenceFeatures().size());
385  4 assertTrue(
386    "Expected at least one CDNA/Protein mapping for seq1",
387    dataset.getCodonFrame(seq1) != null
388    && dataset.getCodonFrame(seq1).size() > 0);
389   
390    }
391   
 
392  1 toggle @Test(groups = { "Functional" })
393    public void readGff3File() throws IOException
394    {
395  1 FeaturesFile gffreader = new FeaturesFile(true, simpleGffFile,
396    DataSourceType.FILE);
397  1 Alignment dataset = new Alignment(gffreader.getSeqsAsArray());
398  1 gffreader.addProperties(dataset);
399  1 checkDatasetfromSimpleGff3(dataset);
400    }
401   
 
402  1 toggle @Test(groups = { "Functional" })
403    public void simpleGff3FileClass() throws IOException
404    {
405  1 AlignmentI dataset = new Alignment(new SequenceI[] {});
406  1 FeaturesFile ffile = new FeaturesFile(simpleGffFile,
407    DataSourceType.FILE);
408   
409  1 boolean parseResult = ffile.parse(dataset, null, false, false);
410  1 assertTrue("return result should be true", parseResult);
411  1 checkDatasetfromSimpleGff3(dataset);
412    }
413   
 
414  1 toggle @Test(groups = { "Functional" })
415    public void simpleGff3FileLoader() throws IOException
416    {
417  1 AlignFrame af = new FileLoader(false).LoadFileWaitTillLoaded(
418    simpleGffFile, DataSourceType.FILE);
419  1 assertTrue(
420    "Didn't read the alignment into an alignframe from Gff3 File",
421    af != null);
422  1 checkDatasetfromSimpleGff3(af.getViewport().getAlignment());
423    }
424   
 
425  1 toggle @Test(groups = { "Functional" })
426    public void simpleGff3RelaxedIdMatching() throws IOException
427    {
428  1 AlignmentI dataset = new Alignment(new SequenceI[] {});
429  1 FeaturesFile ffile = new FeaturesFile(simpleGffFile,
430    DataSourceType.FILE);
431   
432  1 boolean parseResult = ffile.parse(dataset, null, false, true);
433  1 assertTrue("return result (relaxedID matching) should be true",
434    parseResult);
435  1 checkDatasetfromSimpleGff3(dataset);
436    }
437   
 
438  1 toggle @Test(groups = { "Functional" })
439    public void testPrintJalviewFormat() throws Exception
440    {
441  1 File f = new File("examples/uniref50.fa");
442  1 AlignmentI al = readAlignmentFile(f);
443  1 AlignFrame af = new AlignFrame(al, 500, 500);
444  1 Map<String, FeatureColourI> colours = af.getFeatureRenderer()
445    .getFeatureColours();
446  1 String features = "METAL\tcc9900\n"
447    + "GAMMA-TURN\tred|0,255,255|20.0|95.0|below|66.0\n"
448    + "Pfam\tred\n"
449    + "STARTGROUP\tuniprot\n"
450    + "Cath\tFER_CAPAA\t-1\t0\t0\tDomain\n" // non-positional feature
451    + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\n"
452    + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\n"
453    + "<html>Pfam domain<a href=\"http://pfam.xfam.org/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\n"
454    + "ENDGROUP\tuniprot\n";
455  1 FeaturesFile featuresFile = new FeaturesFile(features,
456    DataSourceType.PASTE);
457  1 featuresFile.parse(al.getDataset(), colours, false);
458   
459    /*
460    * add positional and non-positional features with null and
461    * empty feature group to check handled correctly
462    */
463  1 SequenceI seq = al.getSequenceAt(1); // FER_CAPAN
464  1 seq.addSequenceFeature(new SequenceFeature("Pfam", "desc1", 0, 0, 1.3f,
465    null));
466  1 seq.addSequenceFeature(new SequenceFeature("Pfam", "desc2", 4, 9,
467    Float.NaN, null));
468  1 seq = al.getSequenceAt(2); // FER1_SOLLC
469  1 seq.addSequenceFeature(new SequenceFeature("Pfam", "desc3", 0, 0,
470    Float.NaN, ""));
471  1 seq.addSequenceFeature(new SequenceFeature("Pfam", "desc4", 5, 8,
472    -2.6f, ""));
473   
474    /*
475    * first with no features displayed, exclude non-positional features
476    */
477  1 FeatureRenderer fr = af.alignPanel.getFeatureRenderer();
478  1 Map<String, FeatureColourI> visible = fr.getDisplayedFeatureCols();
479  1 List<String> visibleGroups = new ArrayList<>(
480    Arrays.asList(new String[] {}));
481  1 String exported = featuresFile.printJalviewFormat(
482    al.getSequencesArray(), visible, null, visibleGroups, false);
483  1 String expected = "No Features Visible";
484  1 assertEquals(expected, exported);
485   
486    /*
487    * include non-positional features
488    */
489  1 visibleGroups.add("uniprot");
490  1 exported = featuresFile.printJalviewFormat(al.getSequencesArray(),
491    visible, null, visibleGroups, true);
492  1 expected = "Cath\tFER_CAPAA\t-1\t0\t0\tDomain\t0.0\n"
493    + "desc1\tFER_CAPAN\t-1\t0\t0\tPfam\t1.3\n"
494    + "desc3\tFER1_SOLLC\t-1\t0\t0\tPfam\n" // NaN is not output
495    + "\nSTARTGROUP\tuniprot\nENDGROUP\tuniprot\n";
496  1 assertEquals(expected, exported);
497   
498    /*
499    * set METAL (in uniprot group) and GAMMA-TURN visible, but not Pfam
500    */
501  1 fr.setVisible("METAL");
502  1 fr.setVisible("GAMMA-TURN");
503  1 visible = fr.getDisplayedFeatureCols();
504  1 exported = featuresFile.printJalviewFormat(al.getSequencesArray(),
505    visible, null, visibleGroups, false);
506  1 expected = "METAL\tcc9900\n"
507    + "GAMMA-TURN\tscore|ff0000|00ffff|noValueMin|20.0|95.0|below|66.0\n"
508    + "\nSTARTGROUP\tuniprot\n"
509    + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\t0.0\n"
510    + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n"
511    + "ENDGROUP\tuniprot\n";
512  1 assertEquals(expected, exported);
513   
514    /*
515    * now set Pfam visible
516    */
517  1 fr.setVisible("Pfam");
518  1 visible = fr.getDisplayedFeatureCols();
519  1 exported = featuresFile.printJalviewFormat(al.getSequencesArray(),
520    visible, null, visibleGroups, false);
521    /*
522    * features are output within group, ordered by sequence and by type
523    */
524  1 expected = "METAL\tcc9900\n"
525    + "Pfam\tff0000\n"
526    + "GAMMA-TURN\tscore|ff0000|00ffff|noValueMin|20.0|95.0|below|66.0\n"
527    + "\nSTARTGROUP\tuniprot\n"
528    + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\t0.0\n"
529    + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n"
530    + "<html>Pfam domain<a href=\"http://pfam.xfam.org/family/PF00111\">Pfam_3_4</a></html>\tFER_CAPAA\t-1\t20\t20\tPfam\t0.0\n"
531    + "ENDGROUP\tuniprot\n"
532    // null / empty group features output after features in named
533    // groups:
534    + "desc2\tFER_CAPAN\t-1\t4\t9\tPfam\n"
535    + "desc4\tFER1_SOLLC\t-1\t5\t8\tPfam\t-2.6\n";
536  1 assertEquals(expected, exported);
537    }
538   
 
539  1 toggle @Test(groups = { "Functional" })
540    public void testPrintGffFormat() throws Exception
541    {
542  1 File f = new File("examples/uniref50.fa");
543  1 AlignmentI al = readAlignmentFile(f);
544  1 AlignFrame af = new AlignFrame(al, 500, 500);
545   
546    /*
547    * no features
548    */
549  1 FeaturesFile featuresFile = new FeaturesFile();
550  1 FeatureRenderer fr = af.alignPanel.getFeatureRenderer();
551  1 Map<String, FeatureColourI> visible = new HashMap<>();
552  1 List<String> visibleGroups = new ArrayList<>(
553    Arrays.asList(new String[] {}));
554  1 String exported = featuresFile.printGffFormat(al.getSequencesArray(),
555    visible, visibleGroups, false);
556  1 String gffHeader = "##gff-version 2\n";
557  1 assertEquals(gffHeader, exported);
558  1 exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
559    visibleGroups, true);
560  1 assertEquals(gffHeader, exported);
561   
562    /*
563    * add some features
564    */
565  1 al.getSequenceAt(0).addSequenceFeature(
566    new SequenceFeature("Domain", "Cath", 0, 0, 0f, "Uniprot"));
567  1 al.getSequenceAt(0).addSequenceFeature(
568    new SequenceFeature("METAL", "Cath", 39, 39, 1.2f, null));
569  1 al.getSequenceAt(1)
570    .addSequenceFeature(
571    new SequenceFeature("GAMMA-TURN", "Turn", 36, 38, 2.1f,
572    "s3dm"));
573  1 SequenceFeature sf = new SequenceFeature("Pfam", "", 20, 20, 0f,
574    "Uniprot");
575  1 sf.setAttributes("x=y;black=white");
576  1 sf.setStrand("+");
577  1 sf.setPhase("2");
578  1 al.getSequenceAt(1).addSequenceFeature(sf);
579   
580    /*
581    * with no features displayed, exclude non-positional features
582    */
583  1 exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
584    visibleGroups, false);
585  1 assertEquals(gffHeader, exported);
586   
587    /*
588    * include non-positional features
589    */
590  1 visibleGroups.add("Uniprot");
591  1 exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
592    visibleGroups, true);
593  1 String expected = gffHeader
594    + "FER_CAPAA\tUniprot\tDomain\t0\t0\t0.0\t.\t.\n";
595  1 assertEquals(expected, exported);
596   
597    /*
598    * set METAL (in uniprot group) and GAMMA-TURN visible, but not Pfam
599    * only Uniprot group visible here...
600    */
601  1 fr.setVisible("METAL");
602  1 fr.setVisible("GAMMA-TURN");
603  1 visible = fr.getDisplayedFeatureCols();
604  1 exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
605    visibleGroups, false);
606    // METAL feature has null group: description used for column 2
607  1 expected = gffHeader + "FER_CAPAA\tCath\tMETAL\t39\t39\t1.2\t.\t.\n";
608  1 assertEquals(expected, exported);
609   
610    /*
611    * set s3dm group visible
612    */
613  1 visibleGroups.add("s3dm");
614  1 exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
615    visibleGroups, false);
616    // METAL feature has null group: description used for column 2
617  1 expected = gffHeader + "FER_CAPAA\tCath\tMETAL\t39\t39\t1.2\t.\t.\n"
618    + "FER_CAPAN\ts3dm\tGAMMA-TURN\t36\t38\t2.1\t.\t.\n";
619  1 assertEquals(expected, exported);
620   
621    /*
622    * now set Pfam visible
623    */
624  1 fr.setVisible("Pfam");
625  1 visible = fr.getDisplayedFeatureCols();
626  1 exported = featuresFile.printGffFormat(al.getSequencesArray(), visible,
627    visibleGroups, false);
628    // Pfam feature columns include strand(+), phase(2), attributes
629  1 expected = gffHeader
630    + "FER_CAPAA\tCath\tMETAL\t39\t39\t1.2\t.\t.\n"
631    + "FER_CAPAN\ts3dm\tGAMMA-TURN\t36\t38\t2.1\t.\t.\n"
632    + "FER_CAPAN\tUniprot\tPfam\t20\t20\t0.0\t+\t2\tx=y;black=white\n";
633  1 assertEquals(expected, exported);
634    }
635   
636    /**
637    * Test for parsing of feature filters as represented in a Jalview features
638    * file
639    *
640    * @throws Exception
641    */
 
642  1 toggle @Test(groups = { "Functional" })
643    public void testParseFilters() throws Exception
644    {
645  1 Map<String, FeatureMatcherSetI> filters = new HashMap<>();
646  1 String text = "sequence_variant\tCSQ:PolyPhen NotContains 'damaging'\n"
647    + "missense_variant\t(label contains foobar) and (Score lt 1.3)";
648  1 FeaturesFile featuresFile = new FeaturesFile(text,
649    DataSourceType.PASTE);
650  1 featuresFile.parseFilters(filters);
651  1 assertEquals(filters.size(), 2);
652   
653  1 FeatureMatcherSetI fm = filters.get("sequence_variant");
654  1 assertNotNull(fm);
655  1 Iterator<FeatureMatcherI> matchers = fm.getMatchers().iterator();
656  1 FeatureMatcherI matcher = matchers.next();
657  1 assertFalse(matchers.hasNext());
658  1 String[] attributes = matcher.getAttribute();
659  1 assertArrayEquals(attributes, new String[] { "CSQ", "PolyPhen" });
660  1 assertSame(matcher.getMatcher().getCondition(), Condition.NotContains);
661  1 assertEquals(matcher.getMatcher().getPattern(), "damaging");
662   
663  1 fm = filters.get("missense_variant");
664  1 assertNotNull(fm);
665  1 matchers = fm.getMatchers().iterator();
666  1 matcher = matchers.next();
667  1 assertTrue(matcher.isByLabel());
668  1 assertSame(matcher.getMatcher().getCondition(), Condition.Contains);
669  1 assertEquals(matcher.getMatcher().getPattern(), "foobar");
670  1 matcher = matchers.next();
671  1 assertTrue(matcher.isByScore());
672  1 assertSame(matcher.getMatcher().getCondition(), Condition.LT);
673  1 assertEquals(matcher.getMatcher().getPattern(), "1.3");
674  1 assertEquals(matcher.getMatcher().getFloatValue(), 1.3f);
675   
676  1 assertFalse(matchers.hasNext());
677    }
678   
 
679  1 toggle @Test(groups = { "Functional" })
680    public void testOutputFeatureFilters()
681    {
682  1 FeaturesFile ff = new FeaturesFile();
683  1 StringBuilder sb = new StringBuilder();
684  1 Map<String, FeatureColourI> visible = new HashMap<>();
685  1 visible.put("pfam", new FeatureColour(Color.red));
686  1 Map<String, FeatureMatcherSetI> featureFilters = new HashMap<>();
687   
688    // with no filters, nothing is output
689  1 ff.outputFeatureFilters(sb, visible, featureFilters);
690  1 assertEquals("", sb.toString());
691   
692    // with filter for not visible features only, nothing is output
693  1 FeatureMatcherSet filter = new FeatureMatcherSet();
694  1 filter.and(FeatureMatcher.byLabel(Condition.Present, null));
695  1 featureFilters.put("foobar", filter);
696  1 ff.outputFeatureFilters(sb, visible, featureFilters);
697  1 assertEquals("", sb.toString());
698   
699    // with filters for visible feature types
700  1 FeatureMatcherSet filter2 = new FeatureMatcherSet();
701  1 filter2.and(FeatureMatcher.byAttribute(Condition.Present, null, "CSQ",
702    "PolyPhen"));
703  1 filter2.and(FeatureMatcher.byScore(Condition.LE, "-2.4"));
704  1 featureFilters.put("pfam", filter2);
705  1 visible.put("foobar", new FeatureColour(Color.blue));
706  1 ff.outputFeatureFilters(sb, visible, featureFilters);
707  1 String expected = "\nSTARTFILTERS\nfoobar\tLabel Present\npfam\t(CSQ:PolyPhen Present) AND (Score LE -2.4)\nENDFILTERS\n\n";
708  1 assertEquals(expected, sb.toString());
709    }
710    }