Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.datamodel.features

File SequenceFeaturesTest.java

 

Code metrics

0
717
23
1
1,294
919
23
0.03
31.17
23
1

Classes

Class Line # Actions
SequenceFeaturesTest 19 717 23
1.0100%
 

Contributing tests

This file is covered by 22 tests. .

Source view

1    package jalview.datamodel.features;
2   
3    import static org.testng.Assert.assertEquals;
4    import static org.testng.Assert.assertFalse;
5    import static org.testng.Assert.assertSame;
6    import static org.testng.Assert.assertTrue;
7   
8    import java.util.ArrayList;
9    import java.util.Iterator;
10    import java.util.List;
11    import java.util.Map;
12    import java.util.Set;
13   
14    import org.testng.annotations.Test;
15   
16    import jalview.datamodel.SequenceFeature;
17    import junit.extensions.PA;
18   
 
19    public class SequenceFeaturesTest
20    {
 
21  1 toggle @Test(groups = "Functional")
22    public void testConstructor()
23    {
24  1 SequenceFeaturesI store = new SequenceFeatures();
25  1 assertFalse(store.hasFeatures());
26   
27  1 store = new SequenceFeatures((List<SequenceFeature>) null);
28  1 assertFalse(store.hasFeatures());
29   
30  1 List<SequenceFeature> features = new ArrayList<>();
31  1 store = new SequenceFeatures(features);
32  1 assertFalse(store.hasFeatures());
33   
34  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
35    Float.NaN, null);
36  1 features.add(sf1);
37  1 SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 15, 18,
38    Float.NaN, null);
39  1 features.add(sf2); // nested
40  1 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc2", 0, 0,
41    Float.NaN, null); // non-positional
42  1 features.add(sf3);
43  1 store = new SequenceFeatures(features);
44  1 assertTrue(store.hasFeatures());
45  1 assertEquals(2, store.getFeatureCount(true)); // positional
46  1 assertEquals(1, store.getFeatureCount(false)); // non-positional
47  1 assertFalse(store.add(sf1)); // already contained
48  1 assertFalse(store.add(sf2)); // already contained
49  1 assertFalse(store.add(sf3)); // already contained
50    }
51   
 
52  1 toggle @Test(groups = "Functional")
53    public void testGetPositionalFeatures()
54    {
55  1 SequenceFeaturesI store = new SequenceFeatures();
56  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
57    Float.NaN, null);
58  1 store.add(sf1);
59    // same range, different description
60  1 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
61    Float.NaN, null);
62  1 store.add(sf2);
63    // discontiguous range
64  1 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
65    Float.NaN, null);
66  1 store.add(sf3);
67    // overlapping range
68  1 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
69    Float.NaN, null);
70  1 store.add(sf4);
71    // enclosing range
72  1 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
73    Float.NaN, null);
74  1 store.add(sf5);
75    // non-positional feature
76  1 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
77    Float.NaN, null);
78  1 store.add(sf6);
79    // contact feature
80  1 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
81    18, 45, Float.NaN, null);
82  1 store.add(sf7);
83    // different feature type
84  1 SequenceFeature sf8 = new SequenceFeature("Pfam", "desc", 30, 40,
85    Float.NaN, null);
86  1 store.add(sf8);
87  1 SequenceFeature sf9 = new SequenceFeature("Pfam", "desc", 15, 35,
88    Float.NaN, null);
89  1 store.add(sf9);
90   
91    /*
92    * get all positional features
93    */
94  1 List<SequenceFeature> features = store.getPositionalFeatures();
95  1 assertEquals(features.size(), 8);
96  1 assertTrue(features.contains(sf1));
97  1 assertTrue(features.contains(sf2));
98  1 assertTrue(features.contains(sf3));
99  1 assertTrue(features.contains(sf4));
100  1 assertTrue(features.contains(sf5));
101  1 assertFalse(features.contains(sf6)); // non-positional
102  1 assertTrue(features.contains(sf7));
103  1 assertTrue(features.contains(sf8));
104  1 assertTrue(features.contains(sf9));
105   
106    /*
107    * get features by type
108    */
109  1 assertTrue(store.getPositionalFeatures((String) null).isEmpty());
110  1 assertTrue(store.getPositionalFeatures("Cath").isEmpty());
111  1 assertTrue(store.getPositionalFeatures("METAL").isEmpty());
112   
113  1 features = store.getPositionalFeatures("Metal");
114  1 assertEquals(features.size(), 5);
115  1 assertTrue(features.contains(sf1));
116  1 assertTrue(features.contains(sf2));
117  1 assertTrue(features.contains(sf3));
118  1 assertTrue(features.contains(sf4));
119  1 assertTrue(features.contains(sf5));
120  1 assertFalse(features.contains(sf6));
121   
122  1 features = store.getPositionalFeatures("Disulphide bond");
123  1 assertEquals(features.size(), 1);
124  1 assertTrue(features.contains(sf7));
125   
126  1 features = store.getPositionalFeatures("Pfam");
127  1 assertEquals(features.size(), 2);
128  1 assertTrue(features.contains(sf8));
129  1 assertTrue(features.contains(sf9));
130    }
131   
 
132  1 toggle @Test(groups = "Functional")
133    public void testGetContactFeatures()
134    {
135  1 SequenceFeaturesI store = new SequenceFeatures();
136    // non-contact
137  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
138    Float.NaN, null);
139  1 store.add(sf1);
140    // non-positional
141  1 SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
142    Float.NaN, null);
143  1 store.add(sf2);
144    // contact feature
145  1 SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
146    18, 45, Float.NaN, null);
147  1 store.add(sf3);
148    // repeat for different feature type
149  1 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
150    Float.NaN, null);
151  1 store.add(sf4);
152  1 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
153    Float.NaN, null);
154  1 store.add(sf5);
155  1 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
156    45, Float.NaN, null);
157  1 store.add(sf6);
158   
159    /*
160    * get all contact features
161    */
162  1 List<SequenceFeature> features = store.getContactFeatures();
163  1 assertEquals(features.size(), 2);
164  1 assertTrue(features.contains(sf3));
165  1 assertTrue(features.contains(sf6));
166   
167    /*
168    * get contact features by type
169    */
170  1 assertTrue(store.getContactFeatures((String) null).isEmpty());
171  1 assertTrue(store.getContactFeatures("Cath").isEmpty());
172  1 assertTrue(store.getContactFeatures("Pfam").isEmpty());
173  1 assertTrue(store.getContactFeatures("DISULPHIDE BOND").isEmpty());
174   
175  1 features = store.getContactFeatures("Disulphide bond");
176  1 assertEquals(features.size(), 1);
177  1 assertTrue(features.contains(sf3));
178   
179  1 features = store.getContactFeatures("Disulfide bond");
180  1 assertEquals(features.size(), 1);
181  1 assertTrue(features.contains(sf6));
182    }
183   
 
184  1 toggle @Test(groups = "Functional")
185    public void testGetNonPositionalFeatures()
186    {
187  1 SequenceFeaturesI store = new SequenceFeatures();
188    // positional
189  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
190    Float.NaN, null);
191  1 store.add(sf1);
192    // non-positional
193  1 SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
194    Float.NaN, null);
195  1 store.add(sf2);
196    // contact feature
197  1 SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
198    18, 45, Float.NaN, null);
199  1 store.add(sf3);
200    // repeat for different feature type
201  1 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
202    Float.NaN, null);
203  1 store.add(sf4);
204  1 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
205    Float.NaN, null);
206  1 store.add(sf5);
207  1 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
208    45, Float.NaN, null);
209  1 store.add(sf6);
210    // one more non-positional, different description
211  1 SequenceFeature sf7 = new SequenceFeature("Pfam", "desc2", 0, 0,
212    Float.NaN, null);
213  1 store.add(sf7);
214   
215    /*
216    * get all non-positional features
217    */
218  1 List<SequenceFeature> features = store.getNonPositionalFeatures();
219  1 assertEquals(features.size(), 3);
220  1 assertTrue(features.contains(sf2));
221  1 assertTrue(features.contains(sf5));
222  1 assertTrue(features.contains(sf7));
223   
224    /*
225    * get non-positional features by type
226    */
227  1 assertTrue(store.getNonPositionalFeatures((String) null).isEmpty());
228  1 assertTrue(store.getNonPositionalFeatures("Cath").isEmpty());
229  1 assertTrue(store.getNonPositionalFeatures("PFAM").isEmpty());
230   
231  1 features = store.getNonPositionalFeatures("Metal");
232  1 assertEquals(features.size(), 1);
233  1 assertTrue(features.contains(sf2));
234   
235  1 features = store.getNonPositionalFeatures("Pfam");
236  1 assertEquals(features.size(), 2);
237  1 assertTrue(features.contains(sf5));
238  1 assertTrue(features.contains(sf7));
239    }
240   
241    /**
242    * Helper method to add a feature of no particular type
243    *
244    * @param sf
245    * @param type
246    * @param from
247    * @param to
248    * @return
249    */
 
250  14 toggle SequenceFeature addFeature(SequenceFeaturesI sf, String type, int from,
251    int to)
252    {
253  14 SequenceFeature sf1 = new SequenceFeature(type, "", from, to,
254    Float.NaN,
255    null);
256  14 sf.add(sf1);
257  14 return sf1;
258    }
259   
 
260  1 toggle @Test(groups = "Functional")
261    public void testFindFeatures()
262    {
263  1 SequenceFeaturesI sf = new SequenceFeatures();
264  1 SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
265  1 SequenceFeature sf2 = addFeature(sf, "Pfam", 1, 15);
266  1 SequenceFeature sf3 = addFeature(sf, "Pfam", 20, 30);
267  1 SequenceFeature sf4 = addFeature(sf, "Pfam", 40, 100);
268  1 SequenceFeature sf5 = addFeature(sf, "Pfam", 60, 100);
269  1 SequenceFeature sf6 = addFeature(sf, "Pfam", 70, 70);
270  1 SequenceFeature sf7 = addFeature(sf, "Cath", 10, 50);
271  1 SequenceFeature sf8 = addFeature(sf, "Cath", 1, 15);
272  1 SequenceFeature sf9 = addFeature(sf, "Cath", 20, 30);
273  1 SequenceFeature sf10 = addFeature(sf, "Cath", 40, 100);
274  1 SequenceFeature sf11 = addFeature(sf, "Cath", 60, 100);
275  1 SequenceFeature sf12 = addFeature(sf, "Cath", 70, 70);
276   
277  1 List<SequenceFeature> overlaps = sf.findFeatures(200, 200, "Pfam");
278  1 assertTrue(overlaps.isEmpty());
279   
280  1 overlaps = sf.findFeatures( 1, 9, "Pfam");
281  1 assertEquals(overlaps.size(), 1);
282  1 assertTrue(overlaps.contains(sf2));
283   
284  1 overlaps = sf.findFeatures( 5, 18, "Pfam");
285  1 assertEquals(overlaps.size(), 2);
286  1 assertTrue(overlaps.contains(sf1));
287  1 assertTrue(overlaps.contains(sf2));
288   
289  1 overlaps = sf.findFeatures(30, 40, "Pfam");
290  1 assertEquals(overlaps.size(), 3);
291  1 assertTrue(overlaps.contains(sf1));
292  1 assertTrue(overlaps.contains(sf3));
293  1 assertTrue(overlaps.contains(sf4));
294   
295  1 overlaps = sf.findFeatures( 80, 90, "Pfam");
296  1 assertEquals(overlaps.size(), 2);
297  1 assertTrue(overlaps.contains(sf4));
298  1 assertTrue(overlaps.contains(sf5));
299   
300  1 overlaps = sf.findFeatures( 68, 70, "Pfam");
301  1 assertEquals(overlaps.size(), 3);
302  1 assertTrue(overlaps.contains(sf4));
303  1 assertTrue(overlaps.contains(sf5));
304  1 assertTrue(overlaps.contains(sf6));
305   
306  1 overlaps = sf.findFeatures(16, 69, "Cath");
307  1 assertEquals(overlaps.size(), 4);
308  1 assertTrue(overlaps.contains(sf7));
309  1 assertFalse(overlaps.contains(sf8));
310  1 assertTrue(overlaps.contains(sf9));
311  1 assertTrue(overlaps.contains(sf10));
312  1 assertTrue(overlaps.contains(sf11));
313  1 assertFalse(overlaps.contains(sf12));
314   
315  1 assertTrue(sf.findFeatures(0, 1000, "Metal").isEmpty());
316   
317  1 overlaps = sf.findFeatures(7, 7, (String) null);
318  1 assertTrue(overlaps.isEmpty());
319    }
320   
 
321  1 toggle @Test(groups = "Functional")
322    public void testDelete()
323    {
324  1 SequenceFeaturesI sf = new SequenceFeatures();
325  1 SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
326  1 assertTrue(sf.getPositionalFeatures().contains(sf1));
327   
328  1 assertFalse(sf.delete(null));
329  1 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 15, 0f, null);
330  1 assertFalse(sf.delete(sf2)); // not added, can't delete it
331  1 assertTrue(sf.delete(sf1));
332  1 assertTrue(sf.getPositionalFeatures().isEmpty());
333    }
334   
 
335  1 toggle @Test(groups = "Functional")
336    public void testHasFeatures()
337    {
338  1 SequenceFeaturesI sf = new SequenceFeatures();
339  1 assertFalse(sf.hasFeatures());
340   
341  1 SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
342  1 assertTrue(sf.hasFeatures());
343   
344  1 sf.delete(sf1);
345  1 assertFalse(sf.hasFeatures());
346    }
347   
348    /**
349    * Tests for the method that gets feature groups for positional or
350    * non-positional features
351    */
 
352  1 toggle @Test(groups = "Functional")
353    public void testGetFeatureGroups()
354    {
355  1 SequenceFeaturesI sf = new SequenceFeatures();
356  1 assertTrue(sf.getFeatureGroups(true).isEmpty());
357  1 assertTrue(sf.getFeatureGroups(false).isEmpty());
358   
359    /*
360    * add a non-positional feature (begin/end = 0/0)
361    */
362  1 SequenceFeature sfx = new SequenceFeature("AType", "Desc", 0, 0, 0f,
363    "AGroup");
364  1 sf.add(sfx);
365  1 Set<String> groups = sf.getFeatureGroups(true); // for positional
366  1 assertTrue(groups.isEmpty());
367  1 groups = sf.getFeatureGroups(false); // for non-positional
368  1 assertEquals(groups.size(), 1);
369  1 assertTrue(groups.contains("AGroup"));
370  1 groups = sf.getFeatureGroups(false, "AType");
371  1 assertEquals(groups.size(), 1);
372  1 assertTrue(groups.contains("AGroup"));
373  1 groups = sf.getFeatureGroups(true, "AnotherType");
374  1 assertTrue(groups.isEmpty());
375   
376    /*
377    * add, then delete, more non-positional features of different types
378    */
379  1 SequenceFeature sfy = new SequenceFeature("AnotherType", "Desc", 0, 0,
380    0f,
381    "AnotherGroup");
382  1 sf.add(sfy);
383  1 SequenceFeature sfz = new SequenceFeature("AThirdType", "Desc", 0, 0,
384    0f,
385    null);
386  1 sf.add(sfz);
387  1 groups = sf.getFeatureGroups(false);
388  1 assertEquals(groups.size(), 3);
389  1 assertTrue(groups.contains("AGroup"));
390  1 assertTrue(groups.contains("AnotherGroup"));
391  1 assertTrue(groups.contains(null)); // null is a possible group
392  1 sf.delete(sfz);
393  1 sf.delete(sfy);
394  1 groups = sf.getFeatureGroups(false);
395  1 assertEquals(groups.size(), 1);
396  1 assertTrue(groups.contains("AGroup"));
397   
398    /*
399    * add positional features
400    */
401  1 SequenceFeature sf1 = new SequenceFeature("Pfam", "Desc", 10, 50, 0f,
402    "PfamGroup");
403  1 sf.add(sf1);
404  1 groups = sf.getFeatureGroups(true);
405  1 assertEquals(groups.size(), 1);
406  1 assertTrue(groups.contains("PfamGroup"));
407  1 groups = sf.getFeatureGroups(false); // non-positional unchanged
408  1 assertEquals(groups.size(), 1);
409  1 assertTrue(groups.contains("AGroup"));
410   
411  1 SequenceFeature sf2 = new SequenceFeature("Cath", "Desc", 10, 50, 0f,
412    null);
413  1 sf.add(sf2);
414  1 groups = sf.getFeatureGroups(true);
415  1 assertEquals(groups.size(), 2);
416  1 assertTrue(groups.contains("PfamGroup"));
417  1 assertTrue(groups.contains(null));
418   
419  1 sf.delete(sf1);
420  1 sf.delete(sf2);
421  1 assertTrue(sf.getFeatureGroups(true).isEmpty());
422   
423  1 SequenceFeature sf3 = new SequenceFeature("CDS", "", 10, 50, 0f,
424    "Ensembl");
425  1 sf.add(sf3);
426  1 SequenceFeature sf4 = new SequenceFeature("exon", "", 10, 50, 0f,
427    "Ensembl");
428  1 sf.add(sf4);
429  1 groups = sf.getFeatureGroups(true);
430  1 assertEquals(groups.size(), 1);
431  1 assertTrue(groups.contains("Ensembl"));
432   
433    /*
434    * delete last Ensembl group feature from CDS features
435    * but still have one in exon features
436    */
437  1 sf.delete(sf3);
438  1 groups = sf.getFeatureGroups(true);
439  1 assertEquals(groups.size(), 1);
440  1 assertTrue(groups.contains("Ensembl"));
441   
442    /*
443    * delete the last non-positional feature
444    */
445  1 sf.delete(sfx);
446  1 groups = sf.getFeatureGroups(false);
447  1 assertTrue(groups.isEmpty());
448    }
449   
 
450  1 toggle @Test(groups = "Functional")
451    public void testGetFeatureTypesForGroups()
452    {
453  1 SequenceFeaturesI sf = new SequenceFeatures();
454  1 assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
455   
456    /*
457    * add feature with group = "Uniprot", type = "helix"
458    */
459  1 String groupUniprot = "Uniprot";
460  1 SequenceFeature sf1 = new SequenceFeature("helix", "Desc", 10, 50, 0f,
461    groupUniprot);
462  1 sf.add(sf1);
463  1 Set<String> groups = sf.getFeatureTypesForGroups(true, groupUniprot);
464  1 assertEquals(groups.size(), 1);
465  1 assertTrue(groups.contains("helix"));
466  1 assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
467   
468    /*
469    * add feature with group = "Uniprot", type = "strand"
470    */
471  1 SequenceFeature sf2 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
472    groupUniprot);
473  1 sf.add(sf2);
474  1 groups = sf.getFeatureTypesForGroups(true, groupUniprot);
475  1 assertEquals(groups.size(), 2);
476  1 assertTrue(groups.contains("helix"));
477  1 assertTrue(groups.contains("strand"));
478   
479    /*
480    * delete the "strand" Uniprot feature - still have "helix"
481    */
482  1 sf.delete(sf2);
483  1 groups = sf.getFeatureTypesForGroups(true, groupUniprot);
484  1 assertEquals(groups.size(), 1);
485  1 assertTrue(groups.contains("helix"));
486   
487    /*
488    * delete the "helix" Uniprot feature - none left
489    */
490  1 sf.delete(sf1);
491  1 assertTrue(sf.getFeatureTypesForGroups(true, groupUniprot).isEmpty());
492   
493    /*
494    * add some null group features
495    */
496  1 SequenceFeature sf3 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
497    null);
498  1 sf.add(sf3);
499  1 SequenceFeature sf4 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
500    null);
501  1 sf.add(sf4);
502  1 groups = sf.getFeatureTypesForGroups(true, (String) null);
503  1 assertEquals(groups.size(), 2);
504  1 assertTrue(groups.contains("strand"));
505  1 assertTrue(groups.contains("turn"));
506   
507    /*
508    * add strand/Cath and turn/Scop and query for one or both groups
509    * (find feature types for groups selected in Feature Settings)
510    */
511  1 SequenceFeature sf5 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
512    "Cath");
513  1 sf.add(sf5);
514  1 SequenceFeature sf6 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
515    "Scop");
516  1 sf.add(sf6);
517  1 groups = sf.getFeatureTypesForGroups(true, "Cath");
518  1 assertEquals(groups.size(), 1);
519  1 assertTrue(groups.contains("strand"));
520  1 groups = sf.getFeatureTypesForGroups(true, "Scop");
521  1 assertEquals(groups.size(), 1);
522  1 assertTrue(groups.contains("turn"));
523  1 groups = sf.getFeatureTypesForGroups(true, "Cath", "Scop");
524  1 assertEquals(groups.size(), 2);
525  1 assertTrue(groups.contains("turn"));
526  1 assertTrue(groups.contains("strand"));
527    // alternative vararg syntax
528  1 groups = sf.getFeatureTypesForGroups(true, new String[] { "Cath",
529    "Scop" });
530  1 assertEquals(groups.size(), 2);
531  1 assertTrue(groups.contains("turn"));
532  1 assertTrue(groups.contains("strand"));
533    }
534   
 
535  1 toggle @Test(groups = "Functional")
536    public void testGetFeatureTypes()
537    {
538  1 SequenceFeaturesI store = new SequenceFeatures();
539  1 Set<String> types = store.getFeatureTypes();
540  1 assertTrue(types.isEmpty());
541   
542  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
543    Float.NaN, null);
544  1 store.add(sf1);
545  1 types = store.getFeatureTypes();
546  1 assertEquals(types.size(), 1);
547  1 assertTrue(types.contains("Metal"));
548   
549    // null type is rejected...
550  1 SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
551    Float.NaN, null);
552  1 assertFalse(store.add(sf2));
553  1 types = store.getFeatureTypes();
554  1 assertEquals(types.size(), 1);
555  1 assertFalse(types.contains(null));
556  1 assertTrue(types.contains("Metal"));
557   
558    /*
559    * add non-positional feature
560    */
561  1 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
562    Float.NaN, null);
563  1 store.add(sf3);
564  1 types = store.getFeatureTypes();
565  1 assertEquals(types.size(), 2);
566  1 assertTrue(types.contains("Pfam"));
567   
568    /*
569    * add contact feature
570    */
571  1 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
572    10, 20, Float.NaN, null);
573  1 store.add(sf4);
574  1 types = store.getFeatureTypes();
575  1 assertEquals(types.size(), 3);
576  1 assertTrue(types.contains("Disulphide Bond"));
577   
578    /*
579    * add another Pfam
580    */
581  1 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
582    Float.NaN, null);
583  1 store.add(sf5);
584  1 types = store.getFeatureTypes();
585  1 assertEquals(types.size(), 3); // unchanged
586   
587    /*
588    * delete first Pfam - still have one
589    */
590  1 assertTrue(store.delete(sf3));
591  1 types = store.getFeatureTypes();
592  1 assertEquals(types.size(), 3);
593  1 assertTrue(types.contains("Pfam"));
594   
595    /*
596    * delete second Pfam - no longer have one
597    */
598  1 assertTrue(store.delete(sf5));
599  1 types = store.getFeatureTypes();
600  1 assertEquals(types.size(), 2);
601  1 assertFalse(types.contains("Pfam"));
602    }
603   
 
604  1 toggle @Test(groups = "Functional")
605    public void testGetFeatureCount()
606    {
607  1 SequenceFeaturesI store = new SequenceFeatures();
608  1 assertEquals(store.getFeatureCount(true), 0);
609  1 assertEquals(store.getFeatureCount(false), 0);
610   
611    /*
612    * add positional
613    */
614  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
615    Float.NaN, null);
616  1 store.add(sf1);
617  1 assertEquals(store.getFeatureCount(true), 1);
618  1 assertEquals(store.getFeatureCount(false), 0);
619   
620    /*
621    * null feature type is rejected
622    */
623  1 SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
624    Float.NaN, null);
625  1 assertFalse(store.add(sf2));
626  1 assertEquals(store.getFeatureCount(true), 1);
627  1 assertEquals(store.getFeatureCount(false), 0);
628   
629    /*
630    * add non-positional feature
631    */
632  1 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
633    Float.NaN, null);
634  1 store.add(sf3);
635  1 assertEquals(store.getFeatureCount(true), 1);
636  1 assertEquals(store.getFeatureCount(false), 1);
637   
638    /*
639    * add contact feature (counts as 1)
640    */
641  1 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
642    10, 20, Float.NaN, null);
643  1 store.add(sf4);
644  1 assertEquals(store.getFeatureCount(true), 2);
645  1 assertEquals(store.getFeatureCount(false), 1);
646   
647    /*
648    * add another Pfam but this time as a positional feature
649    */
650  1 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
651    Float.NaN, null);
652  1 store.add(sf5);
653  1 assertEquals(store.getFeatureCount(true), 3); // sf1, sf4, sf5
654  1 assertEquals(store.getFeatureCount(false), 1); // sf3
655  1 assertEquals(store.getFeatureCount(true, "Pfam"), 1); // positional
656  1 assertEquals(store.getFeatureCount(false, "Pfam"), 1); // non-positional
657    // search for type==null
658  1 assertEquals(store.getFeatureCount(true, (String) null), 0);
659    // search with no type specified
660  1 assertEquals(store.getFeatureCount(true, (String[]) null), 3);
661  1 assertEquals(store.getFeatureCount(true, "Metal", "Cath"), 1);
662  1 assertEquals(store.getFeatureCount(true, "Disulphide Bond"), 1);
663  1 assertEquals(store.getFeatureCount(true, "Metal", "Pfam", null), 2);
664   
665    /*
666    * delete first Pfam (non-positional)
667    */
668  1 assertTrue(store.delete(sf3));
669  1 assertEquals(store.getFeatureCount(true), 3);
670  1 assertEquals(store.getFeatureCount(false), 0);
671   
672    /*
673    * delete second Pfam (positional)
674    */
675  1 assertTrue(store.delete(sf5));
676  1 assertEquals(store.getFeatureCount(true), 2);
677  1 assertEquals(store.getFeatureCount(false), 0);
678    }
679   
 
680  1 toggle @Test(groups = "Functional")
681    public void testGetAllFeatures()
682    {
683  1 SequenceFeaturesI store = new SequenceFeatures();
684  1 List<SequenceFeature> features = store.getAllFeatures();
685  1 assertTrue(features.isEmpty());
686   
687  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
688    Float.NaN, null);
689  1 store.add(sf1);
690  1 features = store.getAllFeatures();
691  1 assertEquals(features.size(), 1);
692  1 assertTrue(features.contains(sf1));
693   
694  1 SequenceFeature sf2 = new SequenceFeature("Metallic", "desc", 10, 20,
695    Float.NaN, null);
696  1 store.add(sf2);
697  1 features = store.getAllFeatures();
698  1 assertEquals(features.size(), 2);
699  1 assertTrue(features.contains(sf2));
700   
701    /*
702    * add non-positional feature
703    */
704  1 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
705    Float.NaN, null);
706  1 store.add(sf3);
707  1 features = store.getAllFeatures();
708  1 assertEquals(features.size(), 3);
709  1 assertTrue(features.contains(sf3));
710   
711    /*
712    * add contact feature
713    */
714  1 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
715    10, 20, Float.NaN, null);
716  1 store.add(sf4);
717  1 features = store.getAllFeatures();
718  1 assertEquals(features.size(), 4);
719  1 assertTrue(features.contains(sf4));
720   
721    /*
722    * add another Pfam
723    */
724  1 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
725    Float.NaN, null);
726  1 store.add(sf5);
727  1 features = store.getAllFeatures();
728  1 assertEquals(features.size(), 5);
729  1 assertTrue(features.contains(sf5));
730   
731    /*
732    * select by type does not apply to non-positional features
733    */
734  1 features = store.getAllFeatures("Cath");
735  1 assertEquals(features.size(), 1);
736  1 assertTrue(features.contains(sf3));
737   
738  1 features = store.getAllFeatures("Pfam", "Cath", "Metal");
739  1 assertEquals(features.size(), 3);
740  1 assertTrue(features.contains(sf1));
741  1 assertTrue(features.contains(sf3));
742  1 assertTrue(features.contains(sf5));
743   
744    /*
745    * delete first Pfam
746    */
747  1 assertTrue(store.delete(sf3));
748  1 features = store.getAllFeatures();
749  1 assertEquals(features.size(), 4);
750  1 assertFalse(features.contains(sf3));
751   
752    /*
753    * delete second Pfam
754    */
755  1 assertTrue(store.delete(sf5));
756  1 features = store.getAllFeatures();
757  1 assertEquals(features.size(), 3);
758  1 assertFalse(features.contains(sf3));
759    }
760   
 
761  1 toggle @Test(groups = "Functional")
762    public void testGetTotalFeatureLength()
763    {
764  1 SequenceFeaturesI store = new SequenceFeatures();
765  1 assertEquals(store.getTotalFeatureLength(), 0);
766   
767  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
768    Float.NaN, null);
769  1 assertTrue(store.add(sf1));
770  1 assertEquals(store.getTotalFeatureLength(), 11);
771  1 assertEquals(store.getTotalFeatureLength("Metal"), 11);
772  1 assertEquals(store.getTotalFeatureLength("Plastic"), 0);
773   
774    // re-add does nothing!
775  1 assertFalse(store.add(sf1));
776  1 assertEquals(store.getTotalFeatureLength(), 11);
777   
778    /*
779    * add non-positional feature
780    */
781  1 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
782    Float.NaN, null);
783  1 store.add(sf3);
784  1 assertEquals(store.getTotalFeatureLength(), 11);
785   
786    /*
787    * add contact feature - counts 1 to feature length
788    */
789  1 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
790    10, 20, Float.NaN, null);
791  1 store.add(sf4);
792  1 assertEquals(store.getTotalFeatureLength(), 12);
793   
794    /*
795    * add another Pfam
796    */
797  1 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
798    Float.NaN, null);
799  1 store.add(sf5);
800  1 assertEquals(store.getTotalFeatureLength(), 23);
801   
802    /*
803    * delete features
804    */
805  1 assertTrue(store.delete(sf3)); // non-positional
806  1 assertEquals(store.getTotalFeatureLength(), 23); // no change
807   
808  1 assertTrue(store.delete(sf5));
809  1 assertEquals(store.getTotalFeatureLength(), 12);
810   
811  1 assertTrue(store.delete(sf4)); // contact
812  1 assertEquals(store.getTotalFeatureLength(), 11);
813   
814  1 assertTrue(store.delete(sf1));
815  1 assertEquals(store.getTotalFeatureLength(), 0);
816    }
817   
 
818  1 toggle @Test(groups = "Functional")
819    public void testGetMinimumScore_getMaximumScore()
820    {
821  1 SequenceFeatures sf = new SequenceFeatures();
822  1 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 0, 0,
823    Float.NaN, "group"); // non-positional, no score
824  1 sf.add(sf1);
825  1 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 10, 20,
826    Float.NaN, "group"); // positional, no score
827  1 sf.add(sf2);
828  1 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 10, 20, 1f,
829    "group");
830  1 sf.add(sf3);
831  1 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 12, 16, 4f,
832    "group");
833  1 sf.add(sf4);
834  1 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 0, 0, 11f,
835    "group");
836  1 sf.add(sf5);
837  1 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, -7f,
838    "group");
839  1 sf.add(sf6);
840   
841  1 assertEquals(sf.getMinimumScore("nosuchtype", true), Float.NaN);
842  1 assertEquals(sf.getMinimumScore("nosuchtype", false), Float.NaN);
843  1 assertEquals(sf.getMaximumScore("nosuchtype", true), Float.NaN);
844  1 assertEquals(sf.getMaximumScore("nosuchtype", false), Float.NaN);
845   
846    // positional features min-max:
847  1 assertEquals(sf.getMinimumScore("Metal", true), 1f);
848  1 assertEquals(sf.getMaximumScore("Metal", true), 4f);
849  1 assertEquals(sf.getMinimumScore("Cath", true), Float.NaN);
850  1 assertEquals(sf.getMaximumScore("Cath", true), Float.NaN);
851   
852    // non-positional features min-max:
853  1 assertEquals(sf.getMinimumScore("Cath", false), -7f);
854  1 assertEquals(sf.getMaximumScore("Cath", false), 11f);
855  1 assertEquals(sf.getMinimumScore("Metal", false), Float.NaN);
856  1 assertEquals(sf.getMaximumScore("Metal", false), Float.NaN);
857   
858    // delete features; min-max should get recomputed
859  1 sf.delete(sf6);
860  1 assertEquals(sf.getMinimumScore("Cath", false), 11f);
861  1 assertEquals(sf.getMaximumScore("Cath", false), 11f);
862  1 sf.delete(sf4);
863  1 assertEquals(sf.getMinimumScore("Metal", true), 1f);
864  1 assertEquals(sf.getMaximumScore("Metal", true), 1f);
865  1 sf.delete(sf5);
866  1 assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
867  1 assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
868  1 sf.delete(sf3);
869  1 assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
870  1 assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
871  1 sf.delete(sf1);
872  1 sf.delete(sf2);
873  1 assertFalse(sf.hasFeatures());
874  1 assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
875  1 assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
876  1 assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
877  1 assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
878    }
879   
 
880  1 toggle @Test(groups = "Functional")
881    public void testVarargsToTypes()
882    {
883  1 SequenceFeatures sf = new SequenceFeatures();
884  1 sf.add(new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, "group"));
885  1 sf.add(new SequenceFeature("Cath", "desc", 10, 20, Float.NaN, "group"));
886   
887    /*
888    * no type specified - get all types stored
889    * they are returned in keyset (alphabetical) order
890    */
891  1 Map<String, FeatureStore> featureStores = (Map<String, FeatureStore>) PA
892    .getValue(sf, "featureStore");
893   
894  1 Iterable<FeatureStore> types = sf.varargToTypes();
895  1 Iterator<FeatureStore> iterator = types.iterator();
896  1 assertTrue(iterator.hasNext());
897  1 assertSame(iterator.next(), featureStores.get("Cath"));
898  1 assertTrue(iterator.hasNext());
899  1 assertSame(iterator.next(), featureStores.get("Metal"));
900  1 assertFalse(iterator.hasNext());
901   
902    /*
903    * empty array is the same as no vararg parameter supplied
904    * so treated as all stored types
905    */
906  1 types = sf.varargToTypes(new String[] {});
907  1 iterator = types.iterator();
908  1 assertTrue(iterator.hasNext());
909  1 assertSame(iterator.next(), featureStores.get("Cath"));
910  1 assertTrue(iterator.hasNext());
911  1 assertSame(iterator.next(), featureStores.get("Metal"));
912  1 assertFalse(iterator.hasNext());
913   
914    /*
915    * null type specified; this is passed as vararg
916    * String[1] {null}
917    */
918  1 types = sf.varargToTypes((String) null);
919  1 assertFalse(types.iterator().hasNext());
920   
921    /*
922    * null types array specified; this is passed as vararg null
923    */
924  1 types = sf.varargToTypes((String[]) null);
925  1 iterator = types.iterator();
926  1 assertTrue(iterator.hasNext());
927  1 assertSame(iterator.next(), featureStores.get("Cath"));
928  1 assertTrue(iterator.hasNext());
929  1 assertSame(iterator.next(), featureStores.get("Metal"));
930  1 assertFalse(iterator.hasNext());
931   
932    /*
933    * one type specified
934    */
935  1 types = sf.varargToTypes("Metal");
936  1 iterator = types.iterator();
937  1 assertTrue(iterator.hasNext());
938  1 assertSame(iterator.next(), featureStores.get("Metal"));
939  1 assertFalse(iterator.hasNext());
940   
941    /*
942    * two types specified - order is preserved
943    */
944  1 types = sf.varargToTypes("Metal", "Cath");
945  1 iterator = types.iterator();
946  1 assertTrue(iterator.hasNext());
947  1 assertSame(iterator.next(), featureStores.get("Metal"));
948  1 assertTrue(iterator.hasNext());
949  1 assertSame(iterator.next(), featureStores.get("Cath"));
950  1 assertFalse(iterator.hasNext());
951   
952    /*
953    * null type included - should be ignored
954    */
955  1 types = sf.varargToTypes("Metal", null, "Helix");
956  1 iterator = types.iterator();
957  1 assertTrue(iterator.hasNext());
958  1 assertSame(iterator.next(), featureStores.get("Metal"));
959  1 assertFalse(iterator.hasNext());
960    }
961   
 
962  1 toggle @Test(groups = "Functional")
963    public void testGetFeatureTypes_byOntology()
964    {
965  1 SequenceFeaturesI store = new SequenceFeatures();
966   
967  1 SequenceFeature sf1 = new SequenceFeature("transcript", "desc", 10, 20,
968    Float.NaN, null);
969  1 store.add(sf1);
970    // mRNA isA mature_transcript isA transcript
971  1 SequenceFeature sf2 = new SequenceFeature("mRNA", "desc", 10, 20,
972    Float.NaN, null);
973  1 store.add(sf2);
974    // just to prove non-positional feature types are included
975  1 SequenceFeature sf3 = new SequenceFeature("mRNA", "desc", 0, 0,
976    Float.NaN, null);
977  1 store.add(sf3);
978  1 SequenceFeature sf4 = new SequenceFeature("CDS", "desc", 0, 0,
979    Float.NaN, null);
980  1 store.add(sf4);
981   
982  1 Set<String> types = store.getFeatureTypes("transcript");
983  1 assertEquals(types.size(), 2);
984  1 assertTrue(types.contains("transcript"));
985  1 assertTrue(types.contains("mRNA"));
986   
987    // matches include arguments whether SO terms or not
988  1 types = store.getFeatureTypes("transcript", "CDS");
989  1 assertEquals(types.size(), 3);
990  1 assertTrue(types.contains("transcript"));
991  1 assertTrue(types.contains("mRNA"));
992  1 assertTrue(types.contains("CDS"));
993   
994  1 types = store.getFeatureTypes("exon");
995  1 assertTrue(types.isEmpty());
996    }
997   
 
998  1 toggle @Test(groups = "Functional")
999    public void testGetFeaturesByOntology()
1000    {
1001  1 SequenceFeaturesI store = new SequenceFeatures();
1002  1 List<SequenceFeature> features = store.getFeaturesByOntology();
1003  1 assertTrue(features.isEmpty());
1004  1 assertTrue(store.getFeaturesByOntology(new String[] {}).isEmpty());
1005  1 assertTrue(store.getFeaturesByOntology((String[]) null).isEmpty());
1006   
1007  1 SequenceFeature transcriptFeature = new SequenceFeature("transcript", "desc", 10, 20,
1008    Float.NaN, null);
1009  1 store.add(transcriptFeature);
1010   
1011    /*
1012    * mRNA is a sub-type of transcript; added here 'as if' non-positional
1013    * just to show that non-positional features are included in results
1014    */
1015  1 SequenceFeature mrnaFeature = new SequenceFeature("mRNA", "desc", 0, 0,
1016    Float.NaN, null);
1017  1 store.add(mrnaFeature);
1018   
1019  1 SequenceFeature pfamFeature = new SequenceFeature("Pfam", "desc", 30, 40,
1020    Float.NaN, null);
1021  1 store.add(pfamFeature);
1022   
1023    /*
1024    * "transcript" matches both itself and the sub-term "mRNA"
1025    */
1026  1 features = store.getFeaturesByOntology("transcript");
1027  1 assertEquals(features.size(), 2);
1028  1 assertTrue(features.contains(transcriptFeature));
1029  1 assertTrue(features.contains(mrnaFeature));
1030   
1031    /*
1032    * "mRNA" matches itself but not parent term "transcript"
1033    */
1034  1 features = store.getFeaturesByOntology("mRNA");
1035  1 assertEquals(features.size(), 1);
1036  1 assertTrue(features.contains(mrnaFeature));
1037   
1038    /*
1039    * "pfam" is not an SO term but is included as an exact match
1040    */
1041  1 features = store.getFeaturesByOntology("mRNA", "Pfam");
1042  1 assertEquals(features.size(), 2);
1043  1 assertTrue(features.contains(mrnaFeature));
1044  1 assertTrue(features.contains(pfamFeature));
1045   
1046  1 features = store.getFeaturesByOntology("sequence_variant");
1047  1 assertTrue(features.isEmpty());
1048    }
1049   
 
1050  1 toggle @Test(groups = "Functional")
1051    public void testSortFeatures()
1052    {
1053  1 List<SequenceFeature> sfs = new ArrayList<>();
1054  1 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 30,
1055    60,
1056    Float.NaN, null);
1057  1 sfs.add(sf1);
1058  1 SequenceFeature sf2 = new SequenceFeature("Rfam", "desc", 40, 50,
1059    Float.NaN, null);
1060  1 sfs.add(sf2);
1061  1 SequenceFeature sf3 = new SequenceFeature("Rfam", "desc", 50, 60,
1062    Float.NaN, null);
1063  1 sfs.add(sf3);
1064  1 SequenceFeature sf4 = new SequenceFeature("Xfam", "desc", 30,
1065    80,
1066    Float.NaN, null);
1067  1 sfs.add(sf4);
1068  1 SequenceFeature sf5 = new SequenceFeature("Xfam", "desc", 30,
1069    90,
1070    Float.NaN, null);
1071  1 sfs.add(sf5);
1072   
1073    /*
1074    * sort by end position descending, order unchanged if matched
1075    */
1076  1 SequenceFeatures.sortFeatures(sfs, false);
1077  1 assertSame(sfs.get(0), sf5); // end 90
1078  1 assertSame(sfs.get(1), sf4); // end 80
1079  1 assertSame(sfs.get(2), sf1); // end 60, start 50
1080  1 assertSame(sfs.get(3), sf3); // end 60, start 30
1081  1 assertSame(sfs.get(4), sf2); // end 50
1082   
1083    /*
1084    * resort {5, 4, 1, 3, 2} by start position ascending, end descending
1085    */
1086  1 SequenceFeatures.sortFeatures(sfs, true);
1087  1 assertSame(sfs.get(0), sf5); // start 30, end 90
1088  1 assertSame(sfs.get(1), sf4); // start 30, end 80
1089  1 assertSame(sfs.get(2), sf1); // start 30, end 60
1090  1 assertSame(sfs.get(3), sf2); // start 40
1091  1 assertSame(sfs.get(4), sf3); // start 50
1092    }
1093   
 
1094  1 toggle @Test(groups = "Functional")
1095    public void testGetFeaturesForGroup()
1096    {
1097  1 SequenceFeaturesI store = new SequenceFeatures();
1098   
1099  1 List<SequenceFeature> features = store.getFeaturesForGroup(true, null);
1100  1 assertTrue(features.isEmpty());
1101  1 assertTrue(store.getFeaturesForGroup(false, null).isEmpty());
1102  1 assertTrue(store.getFeaturesForGroup(true, "Uniprot").isEmpty());
1103  1 assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
1104   
1105  1 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
1106    null);
1107  1 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
1108    null);
1109  1 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
1110    "Uniprot");
1111  1 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 0, 0, 0f,
1112    "Rfam");
1113  1 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 5, 15, 0f,
1114    null);
1115  1 store.add(sf1);
1116  1 store.add(sf2);
1117  1 store.add(sf3);
1118  1 store.add(sf4);
1119  1 store.add(sf5);
1120   
1121    // positional features for null group, any type
1122  1 features = store.getFeaturesForGroup(true, null);
1123  1 assertEquals(features.size(), 2);
1124  1 assertTrue(features.contains(sf1));
1125  1 assertTrue(features.contains(sf5));
1126   
1127    // positional features for null group, specified type
1128  1 features = store.getFeaturesForGroup(true, null, new String[] { "Pfam",
1129    "Xfam" });
1130  1 assertEquals(features.size(), 1);
1131  1 assertTrue(features.contains(sf1));
1132  1 features = store.getFeaturesForGroup(true, null, new String[] { "Pfam",
1133    "Xfam", "Cath" });
1134  1 assertEquals(features.size(), 2);
1135  1 assertTrue(features.contains(sf1));
1136  1 assertTrue(features.contains(sf5));
1137   
1138    // positional features for non-null group, any type
1139  1 features = store.getFeaturesForGroup(true, "Uniprot");
1140  1 assertEquals(features.size(), 1);
1141  1 assertTrue(features.contains(sf3));
1142  1 assertTrue(store.getFeaturesForGroup(true, "Rfam").isEmpty());
1143   
1144    // positional features for non-null group, specified type
1145  1 features = store.getFeaturesForGroup(true, "Uniprot", "Pfam", "Xfam",
1146    "Rfam");
1147  1 assertEquals(features.size(), 1);
1148  1 assertTrue(features.contains(sf3));
1149  1 assertTrue(store.getFeaturesForGroup(true, "Uniprot", "Cath").isEmpty());
1150   
1151    // non-positional features for null group, any type
1152  1 features = store.getFeaturesForGroup(false, null);
1153  1 assertEquals(features.size(), 1);
1154  1 assertTrue(features.contains(sf2));
1155   
1156    // non-positional features for null group, specified type
1157  1 features = store.getFeaturesForGroup(false, null, "Pfam", "Xfam");
1158  1 assertEquals(features.size(), 1);
1159  1 assertTrue(features.contains(sf2));
1160  1 assertTrue(store.getFeaturesForGroup(false, null, "Cath").isEmpty());
1161   
1162    // non-positional features for non-null group, any type
1163  1 features = store.getFeaturesForGroup(false, "Rfam");
1164  1 assertEquals(features.size(), 1);
1165  1 assertTrue(features.contains(sf4));
1166  1 assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
1167   
1168    // non-positional features for non-null group, specified type
1169  1 features = store.getFeaturesForGroup(false, "Rfam", "Pfam", "Metal");
1170  1 assertEquals(features.size(), 1);
1171  1 assertTrue(features.contains(sf4));
1172  1 assertTrue(store.getFeaturesForGroup(false, "Rfam", "Cath", "Pfam")
1173    .isEmpty());
1174    }
1175   
 
1176  1 toggle @Test(groups = "Functional")
1177    public void testShiftFeatures()
1178    {
1179  1 SequenceFeatures store = new SequenceFeatures();
1180  1 assertFalse(store.shiftFeatures(0, 1));
1181   
1182  1 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
1183  1 store.add(sf1);
1184    // nested feature:
1185  1 SequenceFeature sf2 = new SequenceFeature("Metal", "", 8, 14, 0f, null);
1186  1 store.add(sf2);
1187    // contact feature:
1188  1 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
1189    0f, null);
1190  1 store.add(sf3);
1191    // non-positional feature:
1192  1 SequenceFeature sf4 = new SequenceFeature("Pfam", "", 0, 0, 0f, null);
1193  1 store.add(sf4);
1194   
1195    /*
1196    * shift features right by 5
1197    */
1198  1 assertTrue(store.shiftFeatures(0, 5));
1199   
1200    // non-positional features untouched:
1201  1 List<SequenceFeature> nonPos = store.getNonPositionalFeatures();
1202  1 assertEquals(nonPos.size(), 1);
1203  1 assertTrue(nonPos.contains(sf4));
1204   
1205    // positional features are replaced
1206  1 List<SequenceFeature> pos = store.getPositionalFeatures();
1207  1 assertEquals(pos.size(), 3);
1208  1 assertFalse(pos.contains(sf1));
1209  1 assertFalse(pos.contains(sf2));
1210  1 assertFalse(pos.contains(sf3));
1211  1 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
1212  1 assertEquals(pos.get(0).getBegin(), 7);
1213  1 assertEquals(pos.get(0).getEnd(), 10);
1214  1 assertEquals(pos.get(0).getType(), "Cath");
1215  1 assertEquals(pos.get(1).getBegin(), 13);
1216  1 assertEquals(pos.get(1).getEnd(), 19);
1217  1 assertEquals(pos.get(1).getType(), "Metal");
1218  1 assertEquals(pos.get(2).getBegin(), 28);
1219  1 assertEquals(pos.get(2).getEnd(), 37);
1220  1 assertEquals(pos.get(2).getType(), "Disulfide bond");
1221   
1222    /*
1223    * now shift left by 15
1224    * feature at [7-10] should be removed
1225    * feature at [13-19] should become [1-4]
1226    */
1227  1 assertTrue(store.shiftFeatures(0, -15));
1228  1 pos = store.getPositionalFeatures();
1229  1 assertEquals(pos.size(), 2);
1230  1 SequenceFeatures.sortFeatures(pos, true);
1231  1 assertEquals(pos.get(0).getBegin(), 1);
1232  1 assertEquals(pos.get(0).getEnd(), 4);
1233  1 assertEquals(pos.get(0).getType(), "Metal");
1234  1 assertEquals(pos.get(1).getBegin(), 13);
1235  1 assertEquals(pos.get(1).getEnd(), 22);
1236  1 assertEquals(pos.get(1).getType(), "Disulfide bond");
1237   
1238    /*
1239    * shift right by 4 from column 2
1240    * feature at [1-4] should be unchanged
1241    * feature at [13-22] should become [17-26]
1242    */
1243  1 assertTrue(store.shiftFeatures(2, 4));
1244  1 pos = store.getPositionalFeatures();
1245  1 assertEquals(pos.size(), 2);
1246  1 SequenceFeatures.sortFeatures(pos, true);
1247  1 assertEquals(pos.get(0).getBegin(), 1);
1248  1 assertEquals(pos.get(0).getEnd(), 4);
1249  1 assertEquals(pos.get(0).getType(), "Metal");
1250  1 assertEquals(pos.get(1).getBegin(), 17);
1251  1 assertEquals(pos.get(1).getEnd(), 26);
1252  1 assertEquals(pos.get(1).getType(), "Disulfide bond");
1253   
1254    /*
1255    * shift right from column 18
1256    * should be no updates
1257    */
1258  1 SequenceFeature f1 = pos.get(0);
1259  1 SequenceFeature f2 = pos.get(1);
1260  1 assertFalse(store.shiftFeatures(18, 6));
1261  1 pos = store.getPositionalFeatures();
1262  1 assertEquals(pos.size(), 2);
1263  1 SequenceFeatures.sortFeatures(pos, true);
1264  1 assertSame(pos.get(0), f1);
1265  1 assertSame(pos.get(1), f2);
1266    }
1267   
 
1268  1 toggle @Test(groups = "Functional")
1269    public void testIsOntologyTerm()
1270    {
1271  1 SequenceFeatures store = new SequenceFeatures();
1272  1 assertTrue(store.isOntologyTerm("gobbledygook"));
1273  1 assertTrue(store.isOntologyTerm("transcript", "transcript"));
1274  1 assertTrue(store.isOntologyTerm("mRNA", "transcript"));
1275  1 assertFalse(store.isOntologyTerm("transcript", "mRNA"));
1276  1 assertTrue(store.isOntologyTerm("junk", "transcript", "junk"));
1277  1 assertTrue(store.isOntologyTerm("junk", new String[] {}));
1278  1 assertTrue(store.isOntologyTerm("junk", (String[]) null));
1279    }
1280   
 
1281  1 toggle @Test(groups = "Functional")
1282    public void testDeleteAll()
1283    {
1284  1 SequenceFeaturesI store = new SequenceFeatures();
1285  1 assertFalse(store.hasFeatures());
1286  1 store.deleteAll();
1287  1 assertFalse(store.hasFeatures());
1288  1 store.add(new SequenceFeature("Cath", "Desc", 12, 20, 0f, "Group"));
1289  1 store.add(new SequenceFeature("Pfam", "Desc", 6, 12, 2f, "Group2"));
1290  1 assertTrue(store.hasFeatures());
1291  1 store.deleteAll();
1292  1 assertFalse(store.hasFeatures());
1293    }
1294    }