Clover icon

Coverage Report

  1. Project Clover database Wed Sep 17 2025 10:52:37 BST
  2. Package jalview.io

File AnnotationFileIOTest.java

 

Code metrics

6
172
9
1
416
321
17
0.1
19.11
9
1.89

Classes

Class Line # Actions
AnnotationFileIOTest 47 172 17
0.818181881.8%
 

Contributing tests

This file is covered by 4 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.Assert.assertFalse;
24    import static org.testng.Assert.assertNull;
25    import static org.testng.AssertJUnit.assertEquals;
26    import static org.testng.AssertJUnit.assertNotNull;
27    import static org.testng.AssertJUnit.assertTrue;
28   
29    import java.awt.Color;
30    import java.io.File;
31    import java.util.Hashtable;
32    import java.util.Iterator;
33    import java.util.List;
34   
35    import org.testng.Assert;
36    import org.testng.annotations.BeforeClass;
37    import org.testng.annotations.Test;
38   
39    import jalview.datamodel.AlignmentAnnotation;
40    import jalview.datamodel.AlignmentI;
41    import jalview.datamodel.HiddenColumns;
42    import jalview.datamodel.SequenceGroup;
43    import jalview.gui.AlignFrame;
44    import jalview.gui.JvOptionPane;
45    import jalview.io.AnnotationFile.ViewDef;
46   
 
47    public class AnnotationFileIOTest
48    {
49   
 
50  1 toggle @BeforeClass(alwaysRun = true)
51    public void setUpJvOptionPane()
52    {
53  1 JvOptionPane.setInteractiveMode(false);
54  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
55    }
56   
57    static String TestFiles[][] = { { "Test example annotation import/export",
58    "examples/uniref50.fa", "examples/testdata/example_annot_file.jva" },
59    { "Test multiple combine annotation statements import/export",
60    "examples/uniref50.fa",
61    "examples/testdata/test_combine_annot.jva" },
62    { "Test multiple combine annotation statements with sequence_ref import/export",
63    "examples/uniref50.fa", "examples/testdata/uniref50_iupred.jva" },
64    { "Test group only annotation file parsing results in parser indicating annotation was parsed",
65    "examples/uniref50.fa", "examples/testdata/test_grpannot.jva" },
66    { "Test hiding/showing of insertions on sequence_ref",
67    "examples/uniref50.fa",
68    "examples/testdata/uniref50_seqref.jva" },
69    { "Test example annotation with calcid import/export",
70    "examples/uniref50.fa", "examples/testdata/example_annot_file_calcid.jva" },
71    { "Test example annotation with annotation property import/export",
72    "examples/uniref50.fa", "examples/testdata/example_annot_file_property.jva" }
73    };
74   
 
75  1 toggle @Test(groups = { "Functional" })
76    public void exampleAnnotationFileIO() throws Exception
77    {
78  1 for (String[] testPair : TestFiles)
79    {
80  7 testAnnotationFileIO(testPair[0], new File(testPair[1]),
81    new File(testPair[2]));
82    }
83    }
84   
 
85  14 toggle protected AlignmentI readAlignmentFile(File f)
86    {
87  14 System.out.println("Reading file: " + f);
88  14 String ff = f.getPath();
89  14 try
90    {
91  14 FormatAdapter rf = new FormatAdapter();
92   
93  14 AlignmentI al = rf.readFile(ff, DataSourceType.FILE,
94    new IdentifyFile().identify(ff, DataSourceType.FILE));
95   
96    // make sure dataset is initialised ? not sure about this
97  224 for (int i = 0; i < al.getSequencesArray().length; ++i)
98    {
99  210 al.getSequenceAt(i).createDatasetSequence();
100    }
101  14 assertNotNull("Couldn't read supplied alignment data.", al);
102  14 return al;
103    } catch (Exception e)
104    {
105  0 e.printStackTrace();
106    }
107  0 Assert.fail(
108    "Couln't read the alignment in file '" + f.toString() + "'");
109  0 return null;
110    }
111   
112    /**
113    * test alignment data in given file can be imported, exported and reimported
114    * with no dataloss
115    *
116    * @param f
117    * - source datafile (IdentifyFile.identify() should work with it)
118    * @param ioformat
119    * - label for IO class used to write and read back in the data from
120    * f
121    */
 
122  7 toggle void testAnnotationFileIO(String testname, File f, File annotFile)
123    {
124  7 System.out.println("Test: " + testname + "\nReading annotation file '"
125    + annotFile + "' onto : " + f);
126  7 String af = annotFile.getPath();
127  7 try
128    {
129  7 AlignmentI al = readAlignmentFile(f);
130  7 HiddenColumns cs = new HiddenColumns();
131  7 assertTrue("Test " + testname
132    + "\nAlignment was not annotated - annotation file not imported.",
133    new AnnotationFile().readAnnotationFile(al, cs, af,
134    DataSourceType.FILE));
135   
136  7 AnnotationFile aff = new AnnotationFile();
137    // ViewDef is not used by Jalview
138  7 ViewDef v = aff.new ViewDef(null, al.getHiddenSequences(), cs,
139    new Hashtable());
140  7 String anfileout = new AnnotationFile().printAnnotations(
141    al.getAlignmentAnnotation(), al.getGroups(),
142    al.getProperties(), null, al, v);
143  7 assertTrue("Test " + testname
144    + "\nAlignment annotation file was not regenerated. Null string",
145    anfileout != null);
146  7 assertTrue("Test " + testname
147    + "\nAlignment annotation file was not regenerated. Empty string",
148    anfileout.length() > "JALVIEW_ANNOTATION".length());
149   
150  7 System.out.println(
151    "Output annotation file:\n" + anfileout + "\n<<EOF\n");
152   
153  7 AlignmentI al_new = readAlignmentFile(f);
154  7 assertTrue("Test " + testname
155    + "\nregenerated annotation file did not annotate alignment.",
156    new AnnotationFile().readAnnotationFile(al_new, anfileout,
157    DataSourceType.PASTE));
158   
159    // test for consistency in io
160  7 StockholmFileTest.testAlignmentEquivalence(al, al_new, false, false,
161    false);
162  7 return;
163    } catch (Exception e)
164    {
165  0 e.printStackTrace();
166    }
167  0 Assert.fail("Test " + testname
168    + "\nCouldn't complete Annotation file roundtrip input/output/input test for '"
169    + annotFile + "'.");
170    }
171   
 
172  1 toggle @Test(groups = "Functional")
173    public void testAnnotateAlignmentView()
174    {
175  1 long t1 = System.currentTimeMillis();
176    /*
177    * JAL-3779 test multiple groups of the same name get annotated
178    */
179  1 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
180    ">Seq1\nQRSIL\n>Seq2\nFTHND\n>Seq3\nRPVSL\n",
181    DataSourceType.PASTE);
182  1 long t2 = System.currentTimeMillis();
183  1 System.err.println("t0: " + (t2 - t1));
184    // seq1 and seq3 are in distinct groups both named Group1
185  1 String annotationFile = "JALVIEW_ANNOTATION\nSEQUENCE_GROUP\tGroup1\t*\t*\t1\n"
186    + "SEQUENCE_GROUP\tGroup2\t*\t*\t2\n"
187    + "SEQUENCE_GROUP\tGroup1\t*\t*\t3\n"
188    + "PROPERTIES\tGroup1\toutlineColour=blue\tidColour=red\n";
189  1 new AnnotationFile().annotateAlignmentView(af.getViewport(),
190    annotationFile, DataSourceType.PASTE);
191   
192  1 AlignmentI al = af.getViewport().getAlignment();
193  1 List<SequenceGroup> groups = al.getGroups();
194  1 assertEquals(3, groups.size());
195  1 SequenceGroup sg = groups.get(0);
196  1 assertEquals("Group1", sg.getName());
197  1 assertTrue(sg.contains(al.getSequenceAt(0)));
198  1 assertEquals(Color.BLUE, sg.getOutlineColour());
199  1 assertEquals(Color.RED, sg.getIdColour());
200  1 sg = groups.get(1);
201  1 assertEquals("Group2", sg.getName());
202  1 assertTrue(sg.contains(al.getSequenceAt(1)));
203   
204    /*
205    * the bug fix: a second group of the same name is also given properties
206    */
207  1 sg = groups.get(2);
208  1 assertEquals("Group1", sg.getName());
209  1 assertTrue(sg.contains(al.getSequenceAt(2)));
210  1 assertEquals(Color.BLUE, sg.getOutlineColour());
211  1 assertEquals(Color.RED, sg.getIdColour());
212    }
213   
 
214  1 toggle @Test(groups = "Functional")
215    public void testCalcIdRestore()
216    {
217  1 long t1 = System.currentTimeMillis();
218    /*
219    * JAL-3779 test multiple groups of the same name get annotated
220    */
221  1 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
222    ">Seq1\nQRSIL\n>Seq2\nFTHND\n>Seq3\nRPVSL\n",
223    DataSourceType.PASTE);
224  1 long t2 = System.currentTimeMillis();
225  1 System.err.println("t0: " + (t2 - t1));
226    // seq1 and seq3 are in distinct groups both named Group1
227  1 String annotationFile = "JALVIEW_ANNOTATION\nCALCID\tmyCalcId\tNO_GRAPH\tA Label\tfoolabel\tt|t|t|t\n"
228    + "CALCID\tmyCalcId\tROWPROPERTIES\tA Label\tspecial=property\n"
229    + "NO_GRAPH\tWithout CALCID 1\tfoolabel\tt|t|t|t\n"
230    + "ROWPROPERTIES\tWithout CALCID 1\tspecial=property\n"
231    + "CALCID\tNO_GRAPH\tWithout CALCID 2\tfoolabel\tt|t|t|t\n"
232    + "CALCID\tROWPROPERTIES\tWithout CALCID 2\tspecial=property\n"
233    + "CALCID\tmyCalcId2\tNO_GRAPH\tA Label\tfoolabel\tt|t|t|t\n"
234    + "CALCID\tmyCalcId2\tROWPROPERTIES\tA Label\tspecial=property\n"
235    + "SEQUENCE_REF\tSeq3\n"
236    + "CALCID\tmyCalcId\tNO_GRAPH\tA Label\tfoolabel\tt|t|t|t\n"
237    + "CALCID\tmyCalcId\tROWPROPERTIES\tA Label\tspecial=seqproperty\n"
238    + "SEQUENCE_REF\t\n"
239    + "BAR_GRAPH\tSeqTrack\tseqs 4\tt|t|t|t\tNO_OF_SEQUENCES=4\tNO_OF_TRACKS=1\n"
240    ;
241   
242   
243  1 assertTrue(new AnnotationFile().annotateAlignmentView(af.getViewport(),
244    annotationFile, DataSourceType.PASTE));
245  1 AlignmentI al = af.getViewport().getAlignment();
246  1 int length = al.getAlignmentAnnotation().length;
247  1 AlignmentAnnotation[] alignAnnot = al.getAlignmentAnnotation();
248  1 Iterable<AlignmentAnnotation> myCalcIdRows = al
249    .findAnnotation("myCalcId");
250  1 assertNotNull(myCalcIdRows);
251    // Expect 2 - one for the alignment and one for the sequence
252  1 Iterator<AlignmentAnnotation> rows = myCalcIdRows.iterator();
253  1 assertTrue(rows.hasNext());
254  1 AlignmentAnnotation nextan = rows.next();
255  1 assertEquals(nextan.label, "A Label");
256  1 assertEquals("property", nextan.getProperty("special"));
257  1 assertTrue(nextan.sequenceRef == null);
258   
259   
260    // second expected to be sequence associated
261  1 assertTrue(rows.hasNext());
262  1 nextan = rows.next();
263  1 assertEquals("seqproperty", nextan.getProperty("special"));
264  1 assertTrue(nextan.sequenceRef != null);
265    // Now check that the track is transferred to the dataset
266  1 AlignmentAnnotation dsseqan = nextan.sequenceRef.getDatasetSequence()
267    .getAlignmentAnnotations(nextan.getCalcId(), nextan.label)
268    .get(0);
269  1 assertEquals("seqproperty", dsseqan.getProperty("special"));
270  1 assertFalse(rows.hasNext());
271   
272  1 Iterable<AlignmentAnnotation> myCalcId2Rows = al
273    .findAnnotation("myCalcId2");
274  1 assertNotNull(myCalcId2Rows);
275  1 rows = myCalcId2Rows.iterator();
276  1 assertTrue(rows.hasNext());
277  1 nextan = rows.next();
278  1 assertEquals(nextan.label, "A Label");
279  1 assertEquals("property", nextan.getProperty("special"));
280  1 assertTrue(nextan.sequenceRef == null);
281   
282  1 Iterable<AlignmentAnnotation> withoutCalcIdRows = al
283    .findAnnotation("");
284  1 assertNotNull(withoutCalcIdRows);
285  1 rows = withoutCalcIdRows.iterator();
286  1 assertTrue(rows.hasNext());
287  1 nextan = rows.next();
288  1 assertEquals(nextan.label, "Without CALCID 1");
289  1 assertTrue(rows.hasNext());
290  1 nextan = rows.next();
291  1 assertEquals(nextan.label, "Without CALCID 2");
292  1 assertEquals(-1,nextan.getNoOfSequencesIncluded());
293  1 assertEquals(-1,nextan.getNoOfTracksIncluded());
294   
295    // Check sequence and annotation track counts are imported
296  1 nextan = rows.next();
297  1 assertEquals("SeqTrack",nextan.label);
298  1 assertEquals(4,nextan.getNoOfSequencesIncluded());
299  1 assertEquals(1,nextan.getNoOfTracksIncluded());
300  1 assertFalse(nextan.getProperties().contains(jalview.io.AnnotationFile.NO_OF_SEQUENCES));
301  1 assertFalse(nextan.getProperties().contains(jalview.io.AnnotationFile.NO_OF_TRACKS));
302  1 AlignmentAnnotation consAnn=null;
303  1 long tries=100;
304  ? while (tries-->0 && (consAnn = af.getViewport().getAlignmentConsensusAnnotation())==null
305    || consAnn.getNoOfSequencesIncluded()==-1) {
306  0 try {
307  0 Thread.sleep(30);
308  0 } catch (Exception x) { Assert.fail("Interrupted wating for calculation...");};
309    }
310  1 if (tries==0)
311    {
312  0 Assert.fail("Gave up waiting for consensus calculation.");
313    }
314    // Now check we have expected metadata - ideally we'd do a round trip here..
315  1 String annFile = new jalview.io.AnnotationFile().printAnnotationsForView(af.getViewport());
316  1 assertTrue(annFile.contains("NO_OF_SEQUENCES=4"));
317  1 assertTrue(annFile.contains("NO_OF_TRACKS=1"));
318    // expect at least one NO_OF_SEQUENCES=3 that occurs after 'Consensus'
319  1 assertTrue(annFile.contains("Consensus"));
320  1 int consensusLineEnds = annFile.indexOf("\n",annFile.indexOf("Consensus"));
321  1 int no_of_seq_pos=annFile.indexOf("NO_OF_SEQUENCES=3",annFile.indexOf("Consensus"));
322  1 assertTrue("Couldn't find NO_OF_SEQUENCES after start of Consensus annotation row",no_of_seq_pos>-1);
323  1 assertTrue("Couldn't find NO_OF_SEQUENCES before end of Consensus annotation row",no_of_seq_pos<consensusLineEnds);
324   
325    }
326   
327   
 
328  1 toggle @Test(groups = "Functional")
329    public void testProviderRestore()
330    {
331  1 long t1 = System.currentTimeMillis();
332    /*
333    * JAL-3779 test multiple groups of the same name get annotated
334    */
335  1 AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
336    ">Seq1\nQRSIL\n>Seq2\nFTHND\n>Seq3\nRPVSL\n",
337    DataSourceType.PASTE);
338  1 long t2 = System.currentTimeMillis();
339  1 System.err.println("t0: " + (t2 - t1));
340    // seq1 and seq3 are in distinct groups both named Group1
341  1 String annotationFile = "JALVIEW_ANNOTATION\n"
342    + "CALCID\tmyCalcId\tNO_GRAPH\tA Label\tfoolabel\tt|t|t|t\tSS_PROVIDER=PDB\tproperty2=abc\t4property=xyz\n"
343    + "CALCID\tmyCalcId\tROWPROPERTIES\tA Label\tspecial=property\n"
344    + "CALCID\tmyCalcId\tNO_GRAPH\tA Label\tfoolabel\tt|t|t|t\t\n"
345    + "CALCID\tmyCalcId\tROWPROPERTIES\tA Label\tspecial=property\n"
346    + "SEQUENCE_REF\tSeq3\n"
347    + "\nCALCID\tmyCalcId\tNO_GRAPH\tA Label\tfoolabel\tt|t|t|t\t1.0\t2.0\t3.0\tSS_PROVIDER=JPred\tproperty3=value1\n"
348    + "\nCALCID\tmyCalcId\tROWPROPERTIES\tA Label\tspecial=seqproperty\n";
349  1 new AnnotationFile().annotateAlignmentView(af.getViewport(),
350    annotationFile, DataSourceType.PASTE);
351  1 AlignmentI al = af.getViewport().getAlignment();
352  1 Iterable<AlignmentAnnotation> myCalcIdRows = al
353    .findAnnotation("myCalcId");
354  1 assertNotNull(myCalcIdRows);
355    // Expect 3 - 2 for the alignment and one for the sequence
356  1 Iterator<AlignmentAnnotation> rows = myCalcIdRows.iterator();
357  1 assertTrue(rows.hasNext());
358  1 AlignmentAnnotation nextan = rows.next();
359  1 assertEquals(nextan.label, "A Label");
360  1 assertEquals("property", nextan.getProperty("special"));
361  1 assertEquals("PDB", nextan.getProperty("SS_PROVIDER"));
362  1 assertEquals("abc", nextan.getProperty("property2"));
363  1 assertEquals(null, nextan.getProperty("4property"));
364  1 assertTrue(nextan.sequenceRef == null);
365    // second row without data properties
366  1 assertTrue(rows.hasNext());
367  1 nextan = rows.next();
368  1 assertEquals(nextan.label, "A Label");
369    // third expected to be sequence associated
370  1 assertTrue(rows.hasNext());
371  1 nextan = rows.next();
372  1 assertEquals("seqproperty", nextan.getProperty("special"));
373  1 assertEquals("JPred", nextan.getProperty("SS_PROVIDER"));
374  1 assertEquals("value1", nextan.getProperty("property3"));
375  1 assertEquals(3.0, nextan.score);
376  1 assertTrue(nextan.sequenceRef != null);
377    // Now check that the track is transferred to the dataset
378  1 AlignmentAnnotation dsseqan = nextan.sequenceRef.getDatasetSequence()
379    .getAlignmentAnnotations(nextan.getCalcId(), nextan.label)
380    .get(0);
381  1 assertEquals("seqproperty", dsseqan.getProperty("special"));
382  1 assertEquals("JPred", dsseqan.getProperty("SS_PROVIDER"));
383    }
384   
 
385  0 toggle @Test
386    public void testIsPropertyValueToken() {
387  0 AnnotationFile annotationFile = new AnnotationFile();
388   
389    // Valid cases
390  0 assertTrue(annotationFile.isPropertyValueToken("property=value"));
391  0 assertTrue(annotationFile.isPropertyValueToken("_myProperty123=myValue123"));
392  0 assertTrue(annotationFile.isPropertyValueToken("_myProperty123=123"));
393   
394    // Invalid cases
395  0 assertFalse(annotationFile.isPropertyValueToken("=value")); // no key
396  0 assertFalse(annotationFile.isPropertyValueToken("key=")); // no value
397  0 assertFalse(annotationFile.isPropertyValueToken("123key=value")); // invalid key
398  0 assertFalse(annotationFile.isPropertyValueToken("@key=value")); // invalid key
399  0 assertFalse(annotationFile.isPropertyValueToken("property")); // no =
400  0 assertFalse(annotationFile.isPropertyValueToken("")); // empty string
401    }
402   
 
403  0 toggle @Test
404    public void testValidKeywords() {
405  0 AnnotationFile annotationFile = new AnnotationFile();
406  0 assertTrue(annotationFile.isAnnotationKeyword("BAR_GRAPH"));
407  0 assertTrue(annotationFile.isAnnotationKeyword("bar_graph"));
408  0 assertTrue(annotationFile.isAnnotationKeyword("BarGraph"));
409  0 assertTrue(annotationFile.isAnnotationKeyword("rowproperties"));
410  0 assertTrue(annotationFile.isAnnotationKeyword("VIEW_HIDECOLS"));
411  0 assertFalse(annotationFile.isAnnotationKeyword("INVALID"));
412  0 assertFalse(annotationFile.isAnnotationKeyword("ANNOTATION_ROW"));
413  0 assertFalse(annotationFile.isAnnotationKeyword(null));
414    }
415   
416    }