Clover icon

Coverage Report

  1. Project Clover database Thu Nov 7 2024 17:01:39 GMT
  2. Package jalview.datamodel.features

File FeatureStoreTest.java

 

Code metrics

0
498
20
1
910
643
20
0.04
24.9
20
1

Classes

Class Line # Actions
FeatureStoreTest 36 498 20
0.00%
 

Contributing tests

No tests hitting this source file were found.

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 jalview.datamodel.SequenceFeature;
29   
30    import java.util.ArrayList;
31    import java.util.List;
32    import java.util.Set;
33   
34    import org.testng.annotations.Test;
35   
 
36    public class FeatureStoreTest
37    {
38   
 
39  0 toggle @Test(groups = "Functional")
40    public void testFindFeatures_nonNested()
41    {
42  0 FeatureStore fs = new FeatureStore();
43  0 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN, null));
44    // same range different description
45  0 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
46  0 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
47  0 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
48   
49  0 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
50  0 assertTrue(overlaps.isEmpty());
51   
52  0 overlaps = fs.findOverlappingFeatures(8, 10);
53  0 assertEquals(overlaps.size(), 2);
54  0 assertEquals(overlaps.get(0).getEnd(), 20);
55  0 assertEquals(overlaps.get(1).getEnd(), 20);
56   
57  0 overlaps = fs.findOverlappingFeatures(12, 16);
58  0 assertEquals(overlaps.size(), 3);
59  0 assertEquals(overlaps.get(0).getEnd(), 20);
60  0 assertEquals(overlaps.get(1).getEnd(), 20);
61  0 assertEquals(overlaps.get(2).getEnd(), 25);
62   
63  0 overlaps = fs.findOverlappingFeatures(33, 33);
64  0 assertEquals(overlaps.size(), 1);
65  0 assertEquals(overlaps.get(0).getEnd(), 35);
66    }
67   
 
68  0 toggle @Test(groups = "Functional")
69    public void testFindFeatures_nested()
70    {
71  0 FeatureStore fs = new FeatureStore();
72  0 SequenceFeature sf1 = addFeature(fs, 10, 50);
73  0 SequenceFeature sf2 = addFeature(fs, 10, 40);
74  0 SequenceFeature sf3 = addFeature(fs, 20, 30);
75    // fudge feature at same location but different group (so is added)
76  0 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
77    "different group");
78  0 fs.addFeature(sf4);
79  0 SequenceFeature sf5 = addFeature(fs, 35, 36);
80   
81  0 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
82  0 assertTrue(overlaps.isEmpty());
83   
84  0 overlaps = fs.findOverlappingFeatures(10, 15);
85  0 assertEquals(overlaps.size(), 2);
86  0 assertTrue(overlaps.contains(sf1));
87  0 assertTrue(overlaps.contains(sf2));
88   
89  0 overlaps = fs.findOverlappingFeatures(45, 60);
90  0 assertEquals(overlaps.size(), 1);
91  0 assertTrue(overlaps.contains(sf1));
92   
93  0 overlaps = fs.findOverlappingFeatures(32, 38);
94  0 assertEquals(overlaps.size(), 3);
95  0 assertTrue(overlaps.contains(sf1));
96  0 assertTrue(overlaps.contains(sf2));
97  0 assertTrue(overlaps.contains(sf5));
98   
99  0 overlaps = fs.findOverlappingFeatures(15, 25);
100  0 assertEquals(overlaps.size(), 4);
101  0 assertTrue(overlaps.contains(sf1));
102  0 assertTrue(overlaps.contains(sf2));
103  0 assertTrue(overlaps.contains(sf3));
104  0 assertTrue(overlaps.contains(sf4));
105    }
106   
 
107  0 toggle @Test(groups = "Functional")
108    public void testFindFeatures_mixed()
109    {
110  0 FeatureStore fs = new FeatureStore();
111  0 SequenceFeature sf1 = addFeature(fs, 10, 50);
112  0 SequenceFeature sf2 = addFeature(fs, 1, 15);
113  0 SequenceFeature sf3 = addFeature(fs, 20, 30);
114  0 SequenceFeature sf4 = addFeature(fs, 40, 100);
115  0 SequenceFeature sf5 = addFeature(fs, 60, 100);
116  0 SequenceFeature sf6 = addFeature(fs, 70, 70);
117   
118  0 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
119  0 assertTrue(overlaps.isEmpty());
120   
121  0 overlaps = fs.findOverlappingFeatures(1, 9);
122  0 assertEquals(overlaps.size(), 1);
123  0 assertTrue(overlaps.contains(sf2));
124   
125  0 overlaps = fs.findOverlappingFeatures(5, 18);
126  0 assertEquals(overlaps.size(), 2);
127  0 assertTrue(overlaps.contains(sf1));
128  0 assertTrue(overlaps.contains(sf2));
129   
130  0 overlaps = fs.findOverlappingFeatures(30, 40);
131  0 assertEquals(overlaps.size(), 3);
132  0 assertTrue(overlaps.contains(sf1));
133  0 assertTrue(overlaps.contains(sf3));
134  0 assertTrue(overlaps.contains(sf4));
135   
136  0 overlaps = fs.findOverlappingFeatures(80, 90);
137  0 assertEquals(overlaps.size(), 2);
138  0 assertTrue(overlaps.contains(sf4));
139  0 assertTrue(overlaps.contains(sf5));
140   
141  0 overlaps = fs.findOverlappingFeatures(68, 70);
142  0 assertEquals(overlaps.size(), 3);
143  0 assertTrue(overlaps.contains(sf4));
144  0 assertTrue(overlaps.contains(sf5));
145  0 assertTrue(overlaps.contains(sf6));
146    }
147   
148    /**
149    * Helper method to add a feature of no particular type
150    *
151    * @param fs
152    * @param from
153    * @param to
154    * @return
155    */
 
156  0 toggle SequenceFeature addFeature(FeatureStore fs, int from, int to)
157    {
158  0 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
159    null);
160  0 fs.addFeature(sf1);
161  0 return sf1;
162    }
163   
 
164  0 toggle @Test(groups = "Functional")
165    public void testFindFeatures_contactFeatures()
166    {
167  0 FeatureStore fs = new FeatureStore();
168   
169  0 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
170    20, Float.NaN, null);
171  0 fs.addFeature(sf);
172   
173    /*
174    * neither contact point in range
175    */
176  0 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
177  0 assertTrue(overlaps.isEmpty());
178   
179    /*
180    * neither contact point in range
181    */
182  0 overlaps = fs.findOverlappingFeatures(11, 19);
183  0 assertTrue(overlaps.isEmpty());
184   
185    /*
186    * first contact point in range
187    */
188  0 overlaps = fs.findOverlappingFeatures(5, 15);
189  0 assertEquals(overlaps.size(), 1);
190  0 assertTrue(overlaps.contains(sf));
191   
192    /*
193    * second contact point in range
194    */
195  0 overlaps = fs.findOverlappingFeatures(15, 25);
196  0 assertEquals(overlaps.size(), 1);
197  0 assertTrue(overlaps.contains(sf));
198   
199    /*
200    * both contact points in range
201    */
202  0 overlaps = fs.findOverlappingFeatures(5, 25);
203  0 assertEquals(overlaps.size(), 1);
204  0 assertTrue(overlaps.contains(sf));
205    }
206   
 
207  0 toggle @Test(groups = "Functional")
208    public void testGetPositionalFeatures()
209    {
210  0 FeatureStore store = new FeatureStore();
211  0 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
212    Float.NaN, null);
213  0 store.addFeature(sf1);
214    // same range, different description
215  0 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
216    Float.NaN, null);
217  0 store.addFeature(sf2);
218    // discontiguous range
219  0 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
220    Float.NaN, null);
221  0 store.addFeature(sf3);
222    // overlapping range
223  0 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
224    Float.NaN, null);
225  0 store.addFeature(sf4);
226    // enclosing range
227  0 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
228    Float.NaN, null);
229  0 store.addFeature(sf5);
230    // non-positional feature
231  0 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
232    Float.NaN, null);
233  0 store.addFeature(sf6);
234    // contact feature
235  0 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc", 18,
236    45, Float.NaN, null);
237  0 store.addFeature(sf7);
238   
239  0 List<SequenceFeature> features = store.getPositionalFeatures();
240  0 assertEquals(features.size(), 6);
241  0 assertTrue(features.contains(sf1));
242  0 assertTrue(features.contains(sf2));
243  0 assertTrue(features.contains(sf3));
244  0 assertTrue(features.contains(sf4));
245  0 assertTrue(features.contains(sf5));
246  0 assertFalse(features.contains(sf6));
247  0 assertTrue(features.contains(sf7));
248   
249  0 features = store.getNonPositionalFeatures();
250  0 assertEquals(features.size(), 1);
251  0 assertTrue(features.contains(sf6));
252    }
253   
 
254  0 toggle @Test(groups = "Functional")
255    public void testDelete()
256    {
257  0 FeatureStore store = new FeatureStore();
258  0 SequenceFeature sf1 = addFeature(store, 10, 20);
259  0 assertTrue(store.getPositionalFeatures().contains(sf1));
260   
261    /*
262    * simple deletion
263    */
264  0 assertTrue(store.delete(sf1));
265  0 assertTrue(store.getPositionalFeatures().isEmpty());
266   
267    /*
268    * non-positional feature deletion
269    */
270  0 SequenceFeature sf2 = addFeature(store, 0, 0);
271  0 assertFalse(store.getPositionalFeatures().contains(sf2));
272  0 assertTrue(store.getNonPositionalFeatures().contains(sf2));
273  0 assertTrue(store.delete(sf2));
274  0 assertTrue(store.getNonPositionalFeatures().isEmpty());
275   
276    /*
277    * contact feature deletion
278    */
279  0 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11, 23,
280    Float.NaN, null);
281  0 store.addFeature(sf3);
282  0 assertEquals(store.getPositionalFeatures().size(), 1);
283  0 assertTrue(store.getPositionalFeatures().contains(sf3));
284  0 assertTrue(store.delete(sf3));
285  0 assertTrue(store.getPositionalFeatures().isEmpty());
286   
287    /*
288    * nested feature deletion
289    */
290  0 SequenceFeature sf4 = addFeature(store, 20, 30);
291  0 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
292  0 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
293  0 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
294  0 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
295  0 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
296  0 assertEquals(store.getPositionalFeatures().size(), 6);
297   
298    // delete a node with children - they take its place
299  0 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
300  0 assertEquals(store.getPositionalFeatures().size(), 5);
301  0 assertFalse(store.getPositionalFeatures().contains(sf6));
302   
303    // delete a node with no children
304  0 assertTrue(store.delete(sf7));
305  0 assertEquals(store.getPositionalFeatures().size(), 4);
306  0 assertFalse(store.getPositionalFeatures().contains(sf7));
307   
308    // delete root of NCList
309  0 assertTrue(store.delete(sf5));
310  0 assertEquals(store.getPositionalFeatures().size(), 3);
311  0 assertFalse(store.getPositionalFeatures().contains(sf5));
312   
313    // continue the killing fields
314  0 assertTrue(store.delete(sf4));
315  0 assertEquals(store.getPositionalFeatures().size(), 2);
316  0 assertFalse(store.getPositionalFeatures().contains(sf4));
317   
318  0 assertTrue(store.delete(sf9));
319  0 assertEquals(store.getPositionalFeatures().size(), 1);
320  0 assertFalse(store.getPositionalFeatures().contains(sf9));
321   
322  0 assertTrue(store.delete(sf8));
323  0 assertTrue(store.getPositionalFeatures().isEmpty());
324    }
325   
 
326  0 toggle @Test(groups = "Functional")
327    public void testAddFeature()
328    {
329  0 FeatureStore fs = new FeatureStore();
330   
331  0 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
332    null);
333  0 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
334    null);
335   
336  0 assertTrue(fs.addFeature(sf1));
337  0 assertEquals(fs.getFeatureCount(true), 1); // positional
338  0 assertEquals(fs.getFeatureCount(false), 0); // non-positional
339   
340    /*
341    * re-adding the same or an identical feature should fail
342    */
343  0 assertFalse(fs.addFeature(sf1));
344  0 assertEquals(fs.getFeatureCount(true), 1);
345  0 assertFalse(fs.addFeature(sf2));
346  0 assertEquals(fs.getFeatureCount(true), 1);
347   
348    /*
349    * add non-positional
350    */
351  0 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
352    null);
353  0 assertTrue(fs.addFeature(sf3));
354  0 assertEquals(fs.getFeatureCount(true), 1); // positional
355  0 assertEquals(fs.getFeatureCount(false), 1); // non-positional
356  0 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
357    null);
358  0 assertFalse(fs.addFeature(sf4)); // already stored
359  0 assertEquals(fs.getFeatureCount(true), 1); // positional
360  0 assertEquals(fs.getFeatureCount(false), 1); // non-positional
361   
362    /*
363    * add contact
364    */
365  0 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
366    Float.NaN, null);
367  0 assertTrue(fs.addFeature(sf5));
368  0 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
369  0 assertEquals(fs.getFeatureCount(false), 1); // non-positional
370  0 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
371    Float.NaN, null);
372  0 assertFalse(fs.addFeature(sf6)); // already stored
373  0 assertEquals(fs.getFeatureCount(true), 2); // no change
374  0 assertEquals(fs.getFeatureCount(false), 1); // no change
375    }
376   
 
377  0 toggle @Test(groups = "Functional")
378    public void testIsEmpty()
379    {
380  0 FeatureStore fs = new FeatureStore();
381  0 assertTrue(fs.isEmpty());
382  0 assertEquals(fs.getFeatureCount(true), 0);
383   
384    /*
385    * non-nested feature
386    */
387  0 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
388    null);
389  0 fs.addFeature(sf1);
390  0 assertFalse(fs.isEmpty());
391  0 assertEquals(fs.getFeatureCount(true), 1);
392  0 fs.delete(sf1);
393  0 assertTrue(fs.isEmpty());
394  0 assertEquals(fs.getFeatureCount(true), 0);
395   
396    /*
397    * non-positional feature
398    */
399  0 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
400  0 fs.addFeature(sf1);
401  0 assertFalse(fs.isEmpty());
402  0 assertEquals(fs.getFeatureCount(false), 1); // non-positional
403  0 assertEquals(fs.getFeatureCount(true), 0); // positional
404  0 fs.delete(sf1);
405  0 assertTrue(fs.isEmpty());
406  0 assertEquals(fs.getFeatureCount(false), 0);
407   
408    /*
409    * contact feature
410    */
411  0 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN,
412    null);
413  0 fs.addFeature(sf1);
414  0 assertFalse(fs.isEmpty());
415  0 assertEquals(fs.getFeatureCount(true), 1);
416  0 fs.delete(sf1);
417  0 assertTrue(fs.isEmpty());
418  0 assertEquals(fs.getFeatureCount(true), 0);
419   
420    /*
421    * sf2, sf3 added as nested features
422    */
423  0 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
424  0 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40, Float.NaN,
425    null);
426  0 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35, Float.NaN,
427    null);
428  0 fs.addFeature(sf1);
429  0 fs.addFeature(sf2);
430  0 fs.addFeature(sf3);
431  0 assertEquals(fs.getFeatureCount(true), 3);
432  0 assertTrue(fs.delete(sf1));
433  0 assertEquals(fs.getFeatureCount(true), 2);
434  0 assertEquals(fs.features.size(), 2);
435  0 assertFalse(fs.isEmpty());
436  0 assertTrue(fs.delete(sf2));
437  0 assertEquals(fs.getFeatureCount(true), 1);
438  0 assertFalse(fs.isEmpty());
439  0 assertTrue(fs.delete(sf3));
440  0 assertEquals(fs.getFeatureCount(true), 0);
441  0 assertTrue(fs.isEmpty()); // all gone
442    }
443   
 
444  0 toggle @Test(groups = "Functional")
445    public void testGetFeatureGroups()
446    {
447  0 FeatureStore fs = new FeatureStore();
448  0 assertTrue(fs.getFeatureGroups(true).isEmpty());
449  0 assertTrue(fs.getFeatureGroups(false).isEmpty());
450   
451  0 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f,
452    "group1");
453  0 fs.addFeature(sf1);
454  0 Set<String> groups = fs.getFeatureGroups(true);
455  0 assertEquals(groups.size(), 1);
456  0 assertTrue(groups.contains("group1"));
457   
458    /*
459    * add another feature of the same group, delete one, delete both
460    */
461  0 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f,
462    "group1");
463  0 fs.addFeature(sf2);
464  0 groups = fs.getFeatureGroups(true);
465  0 assertEquals(groups.size(), 1);
466  0 assertTrue(groups.contains("group1"));
467  0 fs.delete(sf2);
468  0 groups = fs.getFeatureGroups(true);
469  0 assertEquals(groups.size(), 1);
470  0 assertTrue(groups.contains("group1"));
471  0 fs.delete(sf1);
472  0 groups = fs.getFeatureGroups(true);
473  0 assertTrue(fs.getFeatureGroups(true).isEmpty());
474   
475  0 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f,
476    "group2");
477  0 fs.addFeature(sf3);
478  0 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f,
479    "Group2");
480  0 fs.addFeature(sf4);
481  0 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f,
482    null);
483  0 fs.addFeature(sf5);
484  0 groups = fs.getFeatureGroups(true);
485  0 assertEquals(groups.size(), 3);
486  0 assertTrue(groups.contains("group2"));
487  0 assertTrue(groups.contains("Group2")); // case sensitive
488  0 assertTrue(groups.contains(null)); // null allowed
489  0 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
490   
491  0 fs.delete(sf3);
492  0 groups = fs.getFeatureGroups(true);
493  0 assertEquals(groups.size(), 2);
494  0 assertFalse(groups.contains("group2"));
495  0 fs.delete(sf4);
496  0 groups = fs.getFeatureGroups(true);
497  0 assertEquals(groups.size(), 1);
498  0 assertFalse(groups.contains("Group2"));
499  0 fs.delete(sf5);
500  0 groups = fs.getFeatureGroups(true);
501  0 assertTrue(groups.isEmpty());
502   
503    /*
504    * add non-positional feature
505    */
506  0 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
507    "CathGroup");
508  0 fs.addFeature(sf6);
509  0 groups = fs.getFeatureGroups(false);
510  0 assertEquals(groups.size(), 1);
511  0 assertTrue(groups.contains("CathGroup"));
512  0 assertTrue(fs.delete(sf6));
513  0 assertTrue(fs.getFeatureGroups(false).isEmpty());
514    }
515   
 
516  0 toggle @Test(groups = "Functional")
517    public void testGetTotalFeatureLength()
518    {
519  0 FeatureStore fs = new FeatureStore();
520  0 assertEquals(fs.getTotalFeatureLength(), 0);
521   
522  0 addFeature(fs, 10, 20); // 11
523  0 assertEquals(fs.getTotalFeatureLength(), 11);
524  0 addFeature(fs, 17, 37); // 21
525  0 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
526  0 assertEquals(fs.getTotalFeatureLength(), 93);
527   
528    // non-positional features don't count
529  0 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
530    "group1");
531  0 fs.addFeature(sf2);
532  0 assertEquals(fs.getTotalFeatureLength(), 93);
533   
534    // contact features count 1
535  0 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc", 15,
536    35, 1f, "group1");
537  0 fs.addFeature(sf3);
538  0 assertEquals(fs.getTotalFeatureLength(), 94);
539   
540  0 assertTrue(fs.delete(sf1));
541  0 assertEquals(fs.getTotalFeatureLength(), 33);
542  0 assertFalse(fs.delete(sf1));
543  0 assertEquals(fs.getTotalFeatureLength(), 33);
544  0 assertTrue(fs.delete(sf2));
545  0 assertEquals(fs.getTotalFeatureLength(), 33);
546  0 assertTrue(fs.delete(sf3));
547  0 assertEquals(fs.getTotalFeatureLength(), 32);
548    }
549   
 
550  0 toggle @Test(groups = "Functional")
551    public void testGetFeatureLength()
552    {
553    /*
554    * positional feature
555    */
556  0 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f,
557    "group1");
558  0 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
559   
560    /*
561    * non-positional feature
562    */
563  0 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
564    "CathGroup");
565  0 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
566   
567    /*
568    * contact feature counts 1
569    */
570  0 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc", 14,
571    28, 1f, "AGroup");
572  0 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
573    }
574   
 
575  0 toggle @Test(groups = "Functional")
576    public void testMin()
577    {
578  0 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
579  0 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
580  0 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
581  0 assertEquals(FeatureStore.min(2f, -3f), -3f);
582    }
583   
 
584  0 toggle @Test(groups = "Functional")
585    public void testMax()
586    {
587  0 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
588  0 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
589  0 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
590  0 assertEquals(FeatureStore.max(2f, -3f), 2f);
591    }
592   
 
593  0 toggle @Test(groups = "Functional")
594    public void testGetMinimumScore_getMaximumScore()
595    {
596  0 FeatureStore fs = new FeatureStore();
597  0 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
598  0 assertEquals(fs.getMaximumScore(true), Float.NaN);
599  0 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
600  0 assertEquals(fs.getMaximumScore(false), Float.NaN);
601   
602    // add features with no score
603  0 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
604    Float.NaN, "group");
605  0 fs.addFeature(sf1);
606  0 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
607    Float.NaN, "group");
608  0 fs.addFeature(sf2);
609  0 assertEquals(fs.getMinimumScore(true), Float.NaN);
610  0 assertEquals(fs.getMaximumScore(true), Float.NaN);
611  0 assertEquals(fs.getMinimumScore(false), Float.NaN);
612  0 assertEquals(fs.getMaximumScore(false), Float.NaN);
613   
614    // add positional features with score
615  0 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
616    "group");
617  0 fs.addFeature(sf3);
618  0 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
619    "group");
620  0 fs.addFeature(sf4);
621  0 assertEquals(fs.getMinimumScore(true), 1f);
622  0 assertEquals(fs.getMaximumScore(true), 4f);
623  0 assertEquals(fs.getMinimumScore(false), Float.NaN);
624  0 assertEquals(fs.getMaximumScore(false), Float.NaN);
625   
626    // add non-positional features with score
627  0 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
628    "group");
629  0 fs.addFeature(sf5);
630  0 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
631    "group");
632  0 fs.addFeature(sf6);
633  0 assertEquals(fs.getMinimumScore(true), 1f);
634  0 assertEquals(fs.getMaximumScore(true), 4f);
635  0 assertEquals(fs.getMinimumScore(false), -7f);
636  0 assertEquals(fs.getMaximumScore(false), 11f);
637   
638    // delete one positional and one non-positional
639    // min-max should be recomputed
640  0 assertTrue(fs.delete(sf6));
641  0 assertTrue(fs.delete(sf3));
642  0 assertEquals(fs.getMinimumScore(true), 4f);
643  0 assertEquals(fs.getMaximumScore(true), 4f);
644  0 assertEquals(fs.getMinimumScore(false), 11f);
645  0 assertEquals(fs.getMaximumScore(false), 11f);
646   
647    // delete remaining features with score
648  0 assertTrue(fs.delete(sf4));
649  0 assertTrue(fs.delete(sf5));
650  0 assertEquals(fs.getMinimumScore(true), Float.NaN);
651  0 assertEquals(fs.getMaximumScore(true), Float.NaN);
652  0 assertEquals(fs.getMinimumScore(false), Float.NaN);
653  0 assertEquals(fs.getMaximumScore(false), Float.NaN);
654   
655    // delete all features
656  0 assertTrue(fs.delete(sf1));
657  0 assertTrue(fs.delete(sf2));
658  0 assertTrue(fs.isEmpty());
659  0 assertEquals(fs.getMinimumScore(true), Float.NaN);
660  0 assertEquals(fs.getMaximumScore(true), Float.NaN);
661  0 assertEquals(fs.getMinimumScore(false), Float.NaN);
662  0 assertEquals(fs.getMaximumScore(false), Float.NaN);
663    }
664   
 
665  0 toggle @Test(groups = "Functional")
666    public void testListContains()
667    {
668  0 assertFalse(FeatureStore.listContains(null, null));
669  0 List<SequenceFeature> features = new ArrayList<>();
670  0 assertFalse(FeatureStore.listContains(features, null));
671   
672  0 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
673    "group1");
674  0 assertFalse(FeatureStore.listContains(null, sf1));
675  0 assertFalse(FeatureStore.listContains(features, sf1));
676   
677  0 features.add(sf1);
678  0 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
679    "group1");
680  0 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
681    "group1");
682   
683    // sf2.equals(sf1) so contains should return true
684  0 assertTrue(FeatureStore.listContains(features, sf2));
685  0 assertFalse(FeatureStore.listContains(features, sf3));
686    }
687   
 
688  0 toggle @Test(groups = "Functional")
689    public void testGetFeaturesForGroup()
690    {
691  0 FeatureStore fs = new FeatureStore();
692   
693    /*
694    * with no features
695    */
696  0 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
697  0 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
698  0 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
699  0 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
700   
701    /*
702    * sf1: positional feature in the null group
703    */
704  0 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
705    null);
706  0 fs.addFeature(sf1);
707  0 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
708  0 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
709  0 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
710  0 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
711  0 assertEquals(features.size(), 1);
712  0 assertTrue(features.contains(sf1));
713   
714    /*
715    * sf2: non-positional feature in the null group
716    * sf3: positional feature in a non-null group
717    * sf4: non-positional feature in a non-null group
718    */
719  0 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
720    null);
721  0 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
722    "Uniprot");
723  0 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
724    "Rfam");
725  0 fs.addFeature(sf2);
726  0 fs.addFeature(sf3);
727  0 fs.addFeature(sf4);
728   
729  0 features = fs.getFeaturesForGroup(true, null);
730  0 assertEquals(features.size(), 1);
731  0 assertTrue(features.contains(sf1));
732   
733  0 features = fs.getFeaturesForGroup(false, null);
734  0 assertEquals(features.size(), 1);
735  0 assertTrue(features.contains(sf2));
736   
737  0 features = fs.getFeaturesForGroup(true, "Uniprot");
738  0 assertEquals(features.size(), 1);
739  0 assertTrue(features.contains(sf3));
740   
741  0 features = fs.getFeaturesForGroup(false, "Rfam");
742  0 assertEquals(features.size(), 1);
743  0 assertTrue(features.contains(sf4));
744    }
745   
 
746  0 toggle @Test(groups = "Functional")
747    public void testShiftFeatures()
748    {
749  0 FeatureStore fs = new FeatureStore();
750  0 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
751   
752  0 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
753  0 fs.addFeature(sf1);
754    // nested feature:
755  0 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
756  0 fs.addFeature(sf2);
757    // contact feature:
758  0 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
759    0f, null);
760  0 fs.addFeature(sf3);
761    // non-positional feature:
762  0 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
763  0 fs.addFeature(sf4);
764   
765    /*
766    * shift all features right by 5
767    */
768  0 assertTrue(fs.shiftFeatures(0, 5));
769   
770    // non-positional features untouched:
771  0 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
772  0 assertEquals(nonPos.size(), 1);
773  0 assertTrue(nonPos.contains(sf4));
774   
775    // positional features are replaced
776  0 List<SequenceFeature> pos = fs.getPositionalFeatures();
777  0 assertEquals(pos.size(), 3);
778  0 assertFalse(pos.contains(sf1));
779  0 assertFalse(pos.contains(sf2));
780  0 assertFalse(pos.contains(sf3));
781  0 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
782  0 assertEquals(pos.get(0).getBegin(), 7);
783  0 assertEquals(pos.get(0).getEnd(), 10);
784  0 assertEquals(pos.get(1).getBegin(), 13);
785  0 assertEquals(pos.get(1).getEnd(), 19);
786  0 assertEquals(pos.get(2).getBegin(), 28);
787  0 assertEquals(pos.get(2).getEnd(), 37);
788   
789    /*
790    * now shift left by 15
791    * feature at [7-10] should be removed
792    * feature at [13-19] should become [1-4]
793    */
794  0 assertTrue(fs.shiftFeatures(0, -15));
795  0 pos = fs.getPositionalFeatures();
796  0 assertEquals(pos.size(), 2);
797  0 SequenceFeatures.sortFeatures(pos, true);
798  0 assertEquals(pos.get(0).getBegin(), 1);
799  0 assertEquals(pos.get(0).getEnd(), 4);
800  0 assertEquals(pos.get(1).getBegin(), 13);
801  0 assertEquals(pos.get(1).getEnd(), 22);
802   
803    /*
804    * shift right by 4 from position 2 onwards
805    * feature at [1-4] unchanged, feature at [13-22] shifts
806    */
807  0 assertTrue(fs.shiftFeatures(2, 4));
808  0 pos = fs.getPositionalFeatures();
809  0 assertEquals(pos.size(), 2);
810  0 SequenceFeatures.sortFeatures(pos, true);
811  0 assertEquals(pos.get(0).getBegin(), 1);
812  0 assertEquals(pos.get(0).getEnd(), 4);
813  0 assertEquals(pos.get(1).getBegin(), 17);
814  0 assertEquals(pos.get(1).getEnd(), 26);
815   
816    /*
817    * shift right by 4 from position 18 onwards
818    * should be no change
819    */
820  0 SequenceFeature f1 = pos.get(0);
821  0 SequenceFeature f2 = pos.get(1);
822  0 assertFalse(fs.shiftFeatures(18, 4)); // no update
823  0 pos = fs.getPositionalFeatures();
824  0 assertEquals(pos.size(), 2);
825  0 SequenceFeatures.sortFeatures(pos, true);
826  0 assertSame(pos.get(0), f1);
827  0 assertSame(pos.get(1), f2);
828    }
829   
 
830  0 toggle @Test(groups = "Functional")
831    public void testDelete_readd()
832    {
833    /*
834    * add a feature and a nested feature
835    */
836  0 FeatureStore store = new FeatureStore();
837  0 SequenceFeature sf1 = addFeature(store, 10, 20);
838    // sf2 is nested in sf1 so will be stored in nestedFeatures
839  0 SequenceFeature sf2 = addFeature(store, 12, 14);
840  0 List<SequenceFeature> features = store.getPositionalFeatures();
841  0 assertEquals(features.size(), 2);
842  0 assertTrue(features.contains(sf1));
843  0 assertTrue(features.contains(sf2));
844  0 assertTrue(store.features.contains(sf1));
845  0 assertTrue(store.features.contains(sf2));
846   
847    /*
848    * delete the first feature
849    */
850  0 assertTrue(store.delete(sf1));
851  0 features = store.getPositionalFeatures();
852  0 assertFalse(features.contains(sf1));
853  0 assertTrue(features.contains(sf2));
854   
855    /*
856    * re-add the 'nested' feature; is it now duplicated?
857    */
858  0 store.addFeature(sf2);
859  0 features = store.getPositionalFeatures();
860  0 assertEquals(features.size(), 1);
861  0 assertTrue(features.contains(sf2));
862    }
863   
 
864  0 toggle @Test(groups = "Functional")
865    public void testContains()
866    {
867  0 FeatureStore fs = new FeatureStore();
868  0 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
869    "group1");
870  0 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
871    "group2");
872  0 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
873    "group1");
874  0 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
875    "group1");
876  0 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
877    Float.NaN, "group1");
878  0 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
879    Float.NaN, "group2");
880   
881  0 fs.addFeature(sf1);
882  0 fs.addFeature(sf3);
883  0 fs.addFeature(sf5);
884  0 assertTrue(fs.contains(sf1)); // positional feature
885  0 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
886  0 assertFalse(fs.contains(sf2)); // different group
887  0 assertTrue(fs.contains(sf3)); // non-positional
888  0 assertTrue(fs.contains(new SequenceFeature(sf3)));
889  0 assertFalse(fs.contains(sf4)); // different score
890  0 assertTrue(fs.contains(sf5)); // contact feature
891  0 assertTrue(fs.contains(new SequenceFeature(sf5)));
892  0 assertFalse(fs.contains(sf6)); // different group
893   
894    /*
895    * add a nested feature
896    */
897  0 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16, Float.NaN,
898    "group1");
899  0 fs.addFeature(sf7);
900  0 assertTrue(fs.contains(sf7));
901  0 assertTrue(fs.contains(new SequenceFeature(sf7)));
902   
903    /*
904    * delete the outer (enclosing, non-nested) feature
905    */
906  0 fs.delete(sf1);
907  0 assertFalse(fs.contains(sf1));
908  0 assertTrue(fs.contains(sf7));
909    }
910    }