1. Project Clover database Fri Dec 6 2024 13:47:14 GMT
  2. Package jalview.datamodel.features

File SequenceFeaturesTest.java

 

Code metrics

0
717
23
1
1,312
917
23
0.03
31.17
23
1

Classes

Class
Line #
Actions
SequenceFeaturesTest 39 717 23
1.0100%
 

Contributing tests

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