Clover icon

Coverage Report

  1. Project Clover database Mon Sep 2 2024 17:57:51 BST
  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
1.0100%
 

Contributing tests

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