1 package jalview.datamodel.features;
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertFalse;
5 import static org.testng.Assert.assertSame;
6 import static org.testng.Assert.assertTrue;
8 import jalview.datamodel.SequenceFeature;
10 import java.util.ArrayList;
11 import java.util.List;
14 import org.testng.annotations.Test;
16 public class FeatureStoreTest
19 @Test(groups = "Functional")
20 public void testFindFeatures_nonNested()
22 FeatureStore fs = new FeatureStore();
23 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
25 // same range different description
26 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
27 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
28 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
30 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
31 assertTrue(overlaps.isEmpty());
33 overlaps = fs.findOverlappingFeatures(8, 10);
34 assertEquals(overlaps.size(), 2);
35 assertEquals(overlaps.get(0).getEnd(), 20);
36 assertEquals(overlaps.get(1).getEnd(), 20);
38 overlaps = fs.findOverlappingFeatures(12, 16);
39 assertEquals(overlaps.size(), 3);
40 assertEquals(overlaps.get(0).getEnd(), 20);
41 assertEquals(overlaps.get(1).getEnd(), 20);
42 assertEquals(overlaps.get(2).getEnd(), 25);
44 overlaps = fs.findOverlappingFeatures(33, 33);
45 assertEquals(overlaps.size(), 1);
46 assertEquals(overlaps.get(0).getEnd(), 35);
49 @Test(groups = "Functional")
50 public void testFindFeatures_nested()
52 FeatureStore fs = new FeatureStore();
53 SequenceFeature sf1 = addFeature(fs, 10, 50);
54 SequenceFeature sf2 = addFeature(fs, 10, 40);
55 SequenceFeature sf3 = addFeature(fs, 20, 30);
56 // fudge feature at same location but different group (so is added)
57 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
60 SequenceFeature sf5 = addFeature(fs, 35, 36);
62 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
63 assertTrue(overlaps.isEmpty());
65 overlaps = fs.findOverlappingFeatures(10, 15);
66 assertEquals(overlaps.size(), 2);
67 assertTrue(overlaps.contains(sf1));
68 assertTrue(overlaps.contains(sf2));
70 overlaps = fs.findOverlappingFeatures(45, 60);
71 assertEquals(overlaps.size(), 1);
72 assertTrue(overlaps.contains(sf1));
74 overlaps = fs.findOverlappingFeatures(32, 38);
75 assertEquals(overlaps.size(), 3);
76 assertTrue(overlaps.contains(sf1));
77 assertTrue(overlaps.contains(sf2));
78 assertTrue(overlaps.contains(sf5));
80 overlaps = fs.findOverlappingFeatures(15, 25);
81 assertEquals(overlaps.size(), 4);
82 assertTrue(overlaps.contains(sf1));
83 assertTrue(overlaps.contains(sf2));
84 assertTrue(overlaps.contains(sf3));
85 assertTrue(overlaps.contains(sf4));
88 @Test(groups = "Functional")
89 public void testFindFeatures_mixed()
91 FeatureStore fs = new FeatureStore();
92 SequenceFeature sf1 = addFeature(fs, 10, 50);
93 SequenceFeature sf2 = addFeature(fs, 1, 15);
94 SequenceFeature sf3 = addFeature(fs, 20, 30);
95 SequenceFeature sf4 = addFeature(fs, 40, 100);
96 SequenceFeature sf5 = addFeature(fs, 60, 100);
97 SequenceFeature sf6 = addFeature(fs, 70, 70);
99 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
100 assertTrue(overlaps.isEmpty());
102 overlaps = fs.findOverlappingFeatures(1, 9);
103 assertEquals(overlaps.size(), 1);
104 assertTrue(overlaps.contains(sf2));
106 overlaps = fs.findOverlappingFeatures(5, 18);
107 assertEquals(overlaps.size(), 2);
108 assertTrue(overlaps.contains(sf1));
109 assertTrue(overlaps.contains(sf2));
111 overlaps = fs.findOverlappingFeatures(30, 40);
112 assertEquals(overlaps.size(), 3);
113 assertTrue(overlaps.contains(sf1));
114 assertTrue(overlaps.contains(sf3));
115 assertTrue(overlaps.contains(sf4));
117 overlaps = fs.findOverlappingFeatures(80, 90);
118 assertEquals(overlaps.size(), 2);
119 assertTrue(overlaps.contains(sf4));
120 assertTrue(overlaps.contains(sf5));
122 overlaps = fs.findOverlappingFeatures(68, 70);
123 assertEquals(overlaps.size(), 3);
124 assertTrue(overlaps.contains(sf4));
125 assertTrue(overlaps.contains(sf5));
126 assertTrue(overlaps.contains(sf6));
130 * Helper method to add a feature of no particular type
137 SequenceFeature addFeature(FeatureStore fs, int from, int to)
139 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
145 @Test(groups = "Functional")
146 public void testFindFeatures_contactFeatures()
148 FeatureStore fs = new FeatureStore();
150 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
151 20, Float.NaN, null);
155 * neither contact point in range
157 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
158 assertTrue(overlaps.isEmpty());
161 * neither contact point in range
163 overlaps = fs.findOverlappingFeatures(11, 19);
164 assertTrue(overlaps.isEmpty());
167 * first contact point in range
169 overlaps = fs.findOverlappingFeatures(5, 15);
170 assertEquals(overlaps.size(), 1);
171 assertTrue(overlaps.contains(sf));
174 * second contact point in range
176 overlaps = fs.findOverlappingFeatures(15, 25);
177 assertEquals(overlaps.size(), 1);
178 assertTrue(overlaps.contains(sf));
181 * both contact points in range
183 overlaps = fs.findOverlappingFeatures(5, 25);
184 assertEquals(overlaps.size(), 1);
185 assertTrue(overlaps.contains(sf));
189 * Tests for the method that returns false for an attempt to add a feature
190 * that would enclose, or be enclosed by, another feature
192 @Test(groups = "Functional")
193 public void testAddNonNestedFeature()
195 FeatureStore fs = new FeatureStore();
197 String type = "Domain";
198 SequenceFeature sf1 = new SequenceFeature(type, type, 10, 20,
200 assertTrue(fs.addNonNestedFeature(sf1));
202 // co-located feature is ok
203 SequenceFeature sf2 = new SequenceFeature(type, type, 10, 20,
205 assertTrue(fs.addNonNestedFeature(sf2));
207 // overlap left is ok
208 SequenceFeature sf3 = new SequenceFeature(type, type, 5, 15, Float.NaN,
210 assertTrue(fs.addNonNestedFeature(sf3));
212 // overlap right is ok
213 SequenceFeature sf4 = new SequenceFeature(type, type, 15, 25,
215 assertTrue(fs.addNonNestedFeature(sf4));
217 // add enclosing feature is not ok
218 SequenceFeature sf5 = new SequenceFeature(type, type, 10, 21,
220 assertFalse(fs.addNonNestedFeature(sf5));
221 SequenceFeature sf6 = new SequenceFeature(type, type, 4, 15, Float.NaN,
223 assertFalse(fs.addNonNestedFeature(sf6));
224 SequenceFeature sf7 = new SequenceFeature(type, type, 1, 50, Float.NaN,
226 assertFalse(fs.addNonNestedFeature(sf7));
228 // add enclosed feature is not ok
229 SequenceFeature sf8 = new SequenceFeature(type, type, 10, 19,
231 assertFalse(fs.addNonNestedFeature(sf8));
232 SequenceFeature sf9 = new SequenceFeature(type, type, 16, 25,
234 assertFalse(fs.addNonNestedFeature(sf9));
235 SequenceFeature sf10 = new SequenceFeature(type, type, 7, 7, Float.NaN,
237 assertFalse(fs.addNonNestedFeature(sf10));
240 @Test(groups = "Functional")
241 public void testGetPositionalFeatures()
243 FeatureStore store = new FeatureStore();
244 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
246 store.addFeature(sf1);
247 // same range, different description
248 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
250 store.addFeature(sf2);
251 // discontiguous range
252 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
254 store.addFeature(sf3);
256 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
258 store.addFeature(sf4);
260 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
262 store.addFeature(sf5);
263 // non-positional feature
264 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
266 store.addFeature(sf6);
268 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
269 18, 45, Float.NaN, null);
270 store.addFeature(sf7);
272 List<SequenceFeature> features = store.getPositionalFeatures();
273 assertEquals(features.size(), 6);
274 assertTrue(features.contains(sf1));
275 assertTrue(features.contains(sf2));
276 assertTrue(features.contains(sf3));
277 assertTrue(features.contains(sf4));
278 assertTrue(features.contains(sf5));
279 assertFalse(features.contains(sf6));
280 assertTrue(features.contains(sf7));
282 features = store.getNonPositionalFeatures();
283 assertEquals(features.size(), 1);
284 assertTrue(features.contains(sf6));
287 @Test(groups = "Functional")
288 public void testDelete()
290 FeatureStore store = new FeatureStore();
291 SequenceFeature sf1 = addFeature(store, 10, 20);
292 assertTrue(store.getPositionalFeatures().contains(sf1));
297 assertTrue(store.delete(sf1));
298 assertTrue(store.getPositionalFeatures().isEmpty());
301 * non-positional feature deletion
303 SequenceFeature sf2 = addFeature(store, 0, 0);
304 assertFalse(store.getPositionalFeatures().contains(sf2));
305 assertTrue(store.getNonPositionalFeatures().contains(sf2));
306 assertTrue(store.delete(sf2));
307 assertTrue(store.getNonPositionalFeatures().isEmpty());
310 * contact feature deletion
312 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
313 23, Float.NaN, null);
314 store.addFeature(sf3);
315 assertEquals(store.getPositionalFeatures().size(), 1);
316 assertTrue(store.getPositionalFeatures().contains(sf3));
317 assertTrue(store.delete(sf3));
318 assertTrue(store.getPositionalFeatures().isEmpty());
321 * nested feature deletion
323 SequenceFeature sf4 = addFeature(store, 20, 30);
324 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
325 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
326 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
327 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
328 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
329 assertEquals(store.getPositionalFeatures().size(), 6);
331 // delete a node with children - they take its place
332 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
333 assertEquals(store.getPositionalFeatures().size(), 5);
334 assertFalse(store.getPositionalFeatures().contains(sf6));
336 // delete a node with no children
337 assertTrue(store.delete(sf7));
338 assertEquals(store.getPositionalFeatures().size(), 4);
339 assertFalse(store.getPositionalFeatures().contains(sf7));
341 // delete root of NCList
342 assertTrue(store.delete(sf5));
343 assertEquals(store.getPositionalFeatures().size(), 3);
344 assertFalse(store.getPositionalFeatures().contains(sf5));
346 // continue the killing fields
347 assertTrue(store.delete(sf4));
348 assertEquals(store.getPositionalFeatures().size(), 2);
349 assertFalse(store.getPositionalFeatures().contains(sf4));
351 assertTrue(store.delete(sf9));
352 assertEquals(store.getPositionalFeatures().size(), 1);
353 assertFalse(store.getPositionalFeatures().contains(sf9));
355 assertTrue(store.delete(sf8));
356 assertTrue(store.getPositionalFeatures().isEmpty());
359 @Test(groups = "Functional")
360 public void testAddFeature()
362 FeatureStore fs = new FeatureStore();
364 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
366 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
369 assertTrue(fs.addFeature(sf1));
370 assertEquals(fs.getFeatureCount(true), 1); // positional
371 assertEquals(fs.getFeatureCount(false), 0); // non-positional
374 * re-adding the same or an identical feature should fail
376 assertFalse(fs.addFeature(sf1));
377 assertEquals(fs.getFeatureCount(true), 1);
378 assertFalse(fs.addFeature(sf2));
379 assertEquals(fs.getFeatureCount(true), 1);
384 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
386 assertTrue(fs.addFeature(sf3));
387 assertEquals(fs.getFeatureCount(true), 1); // positional
388 assertEquals(fs.getFeatureCount(false), 1); // non-positional
389 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
391 assertFalse(fs.addFeature(sf4)); // already stored
392 assertEquals(fs.getFeatureCount(true), 1); // positional
393 assertEquals(fs.getFeatureCount(false), 1); // non-positional
398 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
400 assertTrue(fs.addFeature(sf5));
401 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
402 assertEquals(fs.getFeatureCount(false), 1); // non-positional
403 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
405 assertFalse(fs.addFeature(sf6)); // already stored
406 assertEquals(fs.getFeatureCount(true), 2); // no change
407 assertEquals(fs.getFeatureCount(false), 1); // no change
410 @Test(groups = "Functional")
411 public void testIsEmpty()
413 FeatureStore fs = new FeatureStore();
414 assertTrue(fs.isEmpty());
415 assertEquals(fs.getFeatureCount(true), 0);
420 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
423 assertFalse(fs.isEmpty());
424 assertEquals(fs.getFeatureCount(true), 1);
426 assertTrue(fs.isEmpty());
427 assertEquals(fs.getFeatureCount(true), 0);
430 * non-positional feature
432 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
434 assertFalse(fs.isEmpty());
435 assertEquals(fs.getFeatureCount(false), 1); // non-positional
436 assertEquals(fs.getFeatureCount(true), 0); // positional
438 assertTrue(fs.isEmpty());
439 assertEquals(fs.getFeatureCount(false), 0);
444 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
446 assertFalse(fs.isEmpty());
447 assertEquals(fs.getFeatureCount(true), 1);
449 assertTrue(fs.isEmpty());
450 assertEquals(fs.getFeatureCount(true), 0);
453 * sf2, sf3 added as nested features
455 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
456 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
458 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
463 assertEquals(fs.getFeatureCount(true), 3);
464 assertTrue(fs.delete(sf1));
465 assertEquals(fs.getFeatureCount(true), 2);
466 // FeatureStore should now only contain features in the NCList
467 assertTrue(fs.nonNestedFeatures.isEmpty());
468 assertEquals(fs.nestedFeatures.size(), 2);
469 assertFalse(fs.isEmpty());
470 assertTrue(fs.delete(sf2));
471 assertEquals(fs.getFeatureCount(true), 1);
472 assertFalse(fs.isEmpty());
473 assertTrue(fs.delete(sf3));
474 assertEquals(fs.getFeatureCount(true), 0);
475 assertTrue(fs.isEmpty()); // all gone
478 @Test(groups = "Functional")
479 public void testGetFeatureGroups()
481 FeatureStore fs = new FeatureStore();
482 assertTrue(fs.getFeatureGroups(true).isEmpty());
483 assertTrue(fs.getFeatureGroups(false).isEmpty());
485 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
487 Set<String> groups = fs.getFeatureGroups(true);
488 assertEquals(groups.size(), 1);
489 assertTrue(groups.contains("group1"));
492 * add another feature of the same group, delete one, delete both
494 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
496 groups = fs.getFeatureGroups(true);
497 assertEquals(groups.size(), 1);
498 assertTrue(groups.contains("group1"));
500 groups = fs.getFeatureGroups(true);
501 assertEquals(groups.size(), 1);
502 assertTrue(groups.contains("group1"));
504 groups = fs.getFeatureGroups(true);
505 assertTrue(fs.getFeatureGroups(true).isEmpty());
507 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
509 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
511 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
513 groups = fs.getFeatureGroups(true);
514 assertEquals(groups.size(), 3);
515 assertTrue(groups.contains("group2"));
516 assertTrue(groups.contains("Group2")); // case sensitive
517 assertTrue(groups.contains(null)); // null allowed
518 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
521 groups = fs.getFeatureGroups(true);
522 assertEquals(groups.size(), 2);
523 assertFalse(groups.contains("group2"));
525 groups = fs.getFeatureGroups(true);
526 assertEquals(groups.size(), 1);
527 assertFalse(groups.contains("Group2"));
529 groups = fs.getFeatureGroups(true);
530 assertTrue(groups.isEmpty());
533 * add non-positional feature
535 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
538 groups = fs.getFeatureGroups(false);
539 assertEquals(groups.size(), 1);
540 assertTrue(groups.contains("CathGroup"));
541 assertTrue(fs.delete(sf6));
542 assertTrue(fs.getFeatureGroups(false).isEmpty());
545 @Test(groups = "Functional")
546 public void testGetTotalFeatureLength()
548 FeatureStore fs = new FeatureStore();
549 assertEquals(fs.getTotalFeatureLength(), 0);
551 addFeature(fs, 10, 20); // 11
552 assertEquals(fs.getTotalFeatureLength(), 11);
553 addFeature(fs, 17, 37); // 21
554 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
555 assertEquals(fs.getTotalFeatureLength(), 93);
557 // non-positional features don't count
558 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
561 assertEquals(fs.getTotalFeatureLength(), 93);
563 // contact features count 1
564 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
565 15, 35, 1f, "group1");
567 assertEquals(fs.getTotalFeatureLength(), 94);
569 assertTrue(fs.delete(sf1));
570 assertEquals(fs.getTotalFeatureLength(), 33);
571 assertFalse(fs.delete(sf1));
572 assertEquals(fs.getTotalFeatureLength(), 33);
573 assertTrue(fs.delete(sf2));
574 assertEquals(fs.getTotalFeatureLength(), 33);
575 assertTrue(fs.delete(sf3));
576 assertEquals(fs.getTotalFeatureLength(), 32);
579 @Test(groups = "Functional")
580 public void testGetFeatureLength()
585 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
586 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
589 * non-positional feature
591 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
593 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
596 * contact feature counts 1
598 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
599 14, 28, 1f, "AGroup");
600 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
603 @Test(groups = "Functional")
604 public void testMin()
606 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
607 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
608 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
609 assertEquals(FeatureStore.min(2f, -3f), -3f);
612 @Test(groups = "Functional")
613 public void testMax()
615 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
616 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
617 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
618 assertEquals(FeatureStore.max(2f, -3f), 2f);
621 @Test(groups = "Functional")
622 public void testGetMinimumScore_getMaximumScore()
624 FeatureStore fs = new FeatureStore();
625 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
626 assertEquals(fs.getMaximumScore(true), Float.NaN);
627 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
628 assertEquals(fs.getMaximumScore(false), Float.NaN);
630 // add features with no score
631 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
634 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
637 assertEquals(fs.getMinimumScore(true), Float.NaN);
638 assertEquals(fs.getMaximumScore(true), Float.NaN);
639 assertEquals(fs.getMinimumScore(false), Float.NaN);
640 assertEquals(fs.getMaximumScore(false), Float.NaN);
642 // add positional features with score
643 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
646 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
649 assertEquals(fs.getMinimumScore(true), 1f);
650 assertEquals(fs.getMaximumScore(true), 4f);
651 assertEquals(fs.getMinimumScore(false), Float.NaN);
652 assertEquals(fs.getMaximumScore(false), Float.NaN);
654 // add non-positional features with score
655 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
658 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
661 assertEquals(fs.getMinimumScore(true), 1f);
662 assertEquals(fs.getMaximumScore(true), 4f);
663 assertEquals(fs.getMinimumScore(false), -7f);
664 assertEquals(fs.getMaximumScore(false), 11f);
666 // delete one positional and one non-positional
667 // min-max should be recomputed
668 assertTrue(fs.delete(sf6));
669 assertTrue(fs.delete(sf3));
670 assertEquals(fs.getMinimumScore(true), 4f);
671 assertEquals(fs.getMaximumScore(true), 4f);
672 assertEquals(fs.getMinimumScore(false), 11f);
673 assertEquals(fs.getMaximumScore(false), 11f);
675 // delete remaining features with score
676 assertTrue(fs.delete(sf4));
677 assertTrue(fs.delete(sf5));
678 assertEquals(fs.getMinimumScore(true), Float.NaN);
679 assertEquals(fs.getMaximumScore(true), Float.NaN);
680 assertEquals(fs.getMinimumScore(false), Float.NaN);
681 assertEquals(fs.getMaximumScore(false), Float.NaN);
683 // delete all features
684 assertTrue(fs.delete(sf1));
685 assertTrue(fs.delete(sf2));
686 assertTrue(fs.isEmpty());
687 assertEquals(fs.getMinimumScore(true), Float.NaN);
688 assertEquals(fs.getMaximumScore(true), Float.NaN);
689 assertEquals(fs.getMinimumScore(false), Float.NaN);
690 assertEquals(fs.getMaximumScore(false), Float.NaN);
693 @Test(groups = "Functional")
694 public void testListContains()
696 assertFalse(FeatureStore.listContains(null, null));
697 List<SequenceFeature> features = new ArrayList<SequenceFeature>();
698 assertFalse(FeatureStore.listContains(features, null));
700 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
702 assertFalse(FeatureStore.listContains(null, sf1));
703 assertFalse(FeatureStore.listContains(features, sf1));
706 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
708 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
711 // sf2.equals(sf1) so contains should return true
712 assertTrue(FeatureStore.listContains(features, sf2));
713 assertFalse(FeatureStore.listContains(features, sf3));
716 @Test(groups = "Functional")
717 public void testGetFeaturesForGroup()
719 FeatureStore fs = new FeatureStore();
724 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
725 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
726 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
727 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
730 * sf1: positional feature in the null group
732 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
735 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
736 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
737 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
738 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
739 assertEquals(features.size(), 1);
740 assertTrue(features.contains(sf1));
743 * sf2: non-positional feature in the null group
744 * sf3: positional feature in a non-null group
745 * sf4: non-positional feature in a non-null group
747 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
749 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
751 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
757 features = fs.getFeaturesForGroup(true, null);
758 assertEquals(features.size(), 1);
759 assertTrue(features.contains(sf1));
761 features = fs.getFeaturesForGroup(false, null);
762 assertEquals(features.size(), 1);
763 assertTrue(features.contains(sf2));
765 features = fs.getFeaturesForGroup(true, "Uniprot");
766 assertEquals(features.size(), 1);
767 assertTrue(features.contains(sf3));
769 features = fs.getFeaturesForGroup(false, "Rfam");
770 assertEquals(features.size(), 1);
771 assertTrue(features.contains(sf4));
774 @Test(groups = "Functional")
775 public void testShiftFeatures()
777 FeatureStore fs = new FeatureStore();
778 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
780 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
783 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
786 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
789 // non-positional feature:
790 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
794 * shift all features right by 5
796 assertTrue(fs.shiftFeatures(0, 5));
798 // non-positional features untouched:
799 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
800 assertEquals(nonPos.size(), 1);
801 assertTrue(nonPos.contains(sf4));
803 // positional features are replaced
804 List<SequenceFeature> pos = fs.getPositionalFeatures();
805 assertEquals(pos.size(), 3);
806 assertFalse(pos.contains(sf1));
807 assertFalse(pos.contains(sf2));
808 assertFalse(pos.contains(sf3));
809 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
810 assertEquals(pos.get(0).getBegin(), 7);
811 assertEquals(pos.get(0).getEnd(), 10);
812 assertEquals(pos.get(1).getBegin(), 13);
813 assertEquals(pos.get(1).getEnd(), 19);
814 assertEquals(pos.get(2).getBegin(), 28);
815 assertEquals(pos.get(2).getEnd(), 37);
818 * now shift left by 15
819 * feature at [7-10] should be removed
820 * feature at [13-19] should become [1-4]
822 assertTrue(fs.shiftFeatures(0, -15));
823 pos = fs.getPositionalFeatures();
824 assertEquals(pos.size(), 2);
825 SequenceFeatures.sortFeatures(pos, true);
826 assertEquals(pos.get(0).getBegin(), 1);
827 assertEquals(pos.get(0).getEnd(), 4);
828 assertEquals(pos.get(1).getBegin(), 13);
829 assertEquals(pos.get(1).getEnd(), 22);
832 * shift right by 4 from position 2 onwards
833 * feature at [1-4] unchanged, feature at [13-22] shifts
835 assertTrue(fs.shiftFeatures(2, 4));
836 pos = fs.getPositionalFeatures();
837 assertEquals(pos.size(), 2);
838 SequenceFeatures.sortFeatures(pos, true);
839 assertEquals(pos.get(0).getBegin(), 1);
840 assertEquals(pos.get(0).getEnd(), 4);
841 assertEquals(pos.get(1).getBegin(), 17);
842 assertEquals(pos.get(1).getEnd(), 26);
845 * shift right by 4 from position 18 onwards
846 * should be no change
848 SequenceFeature f1 = pos.get(0);
849 SequenceFeature f2 = pos.get(1);
850 assertFalse(fs.shiftFeatures(18, 4)); // no update
851 pos = fs.getPositionalFeatures();
852 assertEquals(pos.size(), 2);
853 SequenceFeatures.sortFeatures(pos, true);
854 assertSame(pos.get(0), f1);
855 assertSame(pos.get(1), f2);
858 @Test(groups = "Functional")
859 public void testDelete_readd()
862 * add a feature and a nested feature
864 FeatureStore store = new FeatureStore();
865 SequenceFeature sf1 = addFeature(store, 10, 20);
866 // sf2 is nested in sf1 so will be stored in nestedFeatures
867 SequenceFeature sf2 = addFeature(store, 12, 14);
868 List<SequenceFeature> features = store.getPositionalFeatures();
869 assertEquals(features.size(), 2);
870 assertTrue(features.contains(sf1));
871 assertTrue(features.contains(sf2));
872 assertTrue(store.nonNestedFeatures.contains(sf1));
873 assertTrue(store.nestedFeatures.contains(sf2));
876 * delete the first feature
878 assertTrue(store.delete(sf1));
879 features = store.getPositionalFeatures();
880 assertFalse(features.contains(sf1));
881 assertTrue(features.contains(sf2));
884 * re-add the 'nested' feature; is it now duplicated?
886 store.addFeature(sf2);
887 features = store.getPositionalFeatures();
888 assertEquals(features.size(), 1);
889 assertTrue(features.contains(sf2));
892 @Test(groups = "Functional")
893 public void testContains()
895 FeatureStore fs = new FeatureStore();
896 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
897 Float.NaN, "group1");
898 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
899 Float.NaN, "group2");
900 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
902 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
904 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
905 Float.NaN, "group1");
906 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
907 Float.NaN, "group2");
912 assertTrue(fs.contains(sf1)); // positional feature
913 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
914 assertFalse(fs.contains(sf2)); // different group
915 assertTrue(fs.contains(sf3)); // non-positional
916 assertTrue(fs.contains(new SequenceFeature(sf3)));
917 assertFalse(fs.contains(sf4)); // different score
918 assertTrue(fs.contains(sf5)); // contact feature
919 assertTrue(fs.contains(new SequenceFeature(sf5)));
920 assertFalse(fs.contains(sf6)); // different group
923 * add a nested feature
925 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
926 Float.NaN, "group1");
928 assertTrue(fs.contains(sf7));
929 assertTrue(fs.contains(new SequenceFeature(sf7)));
932 * delete the outer (enclosing, non-nested) feature
935 assertFalse(fs.contains(sf1));
936 assertTrue(fs.contains(sf7));