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.assertTrue;
7 import jalview.datamodel.SequenceFeature;
9 import java.util.ArrayList;
10 import java.util.List;
13 import org.testng.annotations.Test;
15 public class FeatureStoreTest
18 @Test(groups = "Functional")
19 public void testFindFeatures_nonNested()
21 FeatureStore fs = new FeatureStore();
22 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
24 // same range different description
25 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
26 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
27 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
29 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
30 assertTrue(overlaps.isEmpty());
32 overlaps = fs.findOverlappingFeatures(8, 10);
33 assertEquals(overlaps.size(), 2);
34 assertEquals(overlaps.get(0).getEnd(), 20);
35 assertEquals(overlaps.get(1).getEnd(), 20);
37 overlaps = fs.findOverlappingFeatures(12, 16);
38 assertEquals(overlaps.size(), 3);
39 assertEquals(overlaps.get(0).getEnd(), 20);
40 assertEquals(overlaps.get(1).getEnd(), 20);
41 assertEquals(overlaps.get(2).getEnd(), 25);
43 overlaps = fs.findOverlappingFeatures(33, 33);
44 assertEquals(overlaps.size(), 1);
45 assertEquals(overlaps.get(0).getEnd(), 35);
48 @Test(groups = "Functional")
49 public void testFindFeatures_nested()
51 FeatureStore fs = new FeatureStore();
52 SequenceFeature sf1 = addFeature(fs, 10, 50);
53 SequenceFeature sf2 = addFeature(fs, 10, 40);
54 SequenceFeature sf3 = addFeature(fs, 20, 30);
55 // fudge feature at same location but different group (so is added)
56 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
59 SequenceFeature sf5 = addFeature(fs, 35, 36);
61 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
62 assertTrue(overlaps.isEmpty());
64 overlaps = fs.findOverlappingFeatures(10, 15);
65 assertEquals(overlaps.size(), 2);
66 assertTrue(overlaps.contains(sf1));
67 assertTrue(overlaps.contains(sf2));
69 overlaps = fs.findOverlappingFeatures(45, 60);
70 assertEquals(overlaps.size(), 1);
71 assertTrue(overlaps.contains(sf1));
73 overlaps = fs.findOverlappingFeatures(32, 38);
74 assertEquals(overlaps.size(), 3);
75 assertTrue(overlaps.contains(sf1));
76 assertTrue(overlaps.contains(sf2));
77 assertTrue(overlaps.contains(sf5));
79 overlaps = fs.findOverlappingFeatures(15, 25);
80 assertEquals(overlaps.size(), 4);
81 assertTrue(overlaps.contains(sf1));
82 assertTrue(overlaps.contains(sf2));
83 assertTrue(overlaps.contains(sf3));
84 assertTrue(overlaps.contains(sf4));
87 @Test(groups = "Functional")
88 public void testFindFeatures_mixed()
90 FeatureStore fs = new FeatureStore();
91 SequenceFeature sf1 = addFeature(fs, 10, 50);
92 SequenceFeature sf2 = addFeature(fs, 1, 15);
93 SequenceFeature sf3 = addFeature(fs, 20, 30);
94 SequenceFeature sf4 = addFeature(fs, 40, 100);
95 SequenceFeature sf5 = addFeature(fs, 60, 100);
96 SequenceFeature sf6 = addFeature(fs, 70, 70);
98 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
99 assertTrue(overlaps.isEmpty());
101 overlaps = fs.findOverlappingFeatures(1, 9);
102 assertEquals(overlaps.size(), 1);
103 assertTrue(overlaps.contains(sf2));
105 overlaps = fs.findOverlappingFeatures(5, 18);
106 assertEquals(overlaps.size(), 2);
107 assertTrue(overlaps.contains(sf1));
108 assertTrue(overlaps.contains(sf2));
110 overlaps = fs.findOverlappingFeatures(30, 40);
111 assertEquals(overlaps.size(), 3);
112 assertTrue(overlaps.contains(sf1));
113 assertTrue(overlaps.contains(sf3));
114 assertTrue(overlaps.contains(sf4));
116 overlaps = fs.findOverlappingFeatures(80, 90);
117 assertEquals(overlaps.size(), 2);
118 assertTrue(overlaps.contains(sf4));
119 assertTrue(overlaps.contains(sf5));
121 overlaps = fs.findOverlappingFeatures(68, 70);
122 assertEquals(overlaps.size(), 3);
123 assertTrue(overlaps.contains(sf4));
124 assertTrue(overlaps.contains(sf5));
125 assertTrue(overlaps.contains(sf6));
129 * Helper method to add a feature of no particular type
136 SequenceFeature addFeature(FeatureStore fs, int from, int to)
138 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
144 @Test(groups = "Functional")
145 public void testFindFeatures_contactFeatures()
147 FeatureStore fs = new FeatureStore();
149 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
150 20, Float.NaN, null);
154 * neither contact point in range
156 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
157 assertTrue(overlaps.isEmpty());
160 * neither contact point in range
162 overlaps = fs.findOverlappingFeatures(11, 19);
163 assertTrue(overlaps.isEmpty());
166 * first contact point in range
168 overlaps = fs.findOverlappingFeatures(5, 15);
169 assertEquals(overlaps.size(), 1);
170 assertTrue(overlaps.contains(sf));
173 * second contact point in range
175 overlaps = fs.findOverlappingFeatures(15, 25);
176 assertEquals(overlaps.size(), 1);
177 assertTrue(overlaps.contains(sf));
180 * both contact points in range
182 overlaps = fs.findOverlappingFeatures(5, 25);
183 assertEquals(overlaps.size(), 1);
184 assertTrue(overlaps.contains(sf));
188 * Tests for the method that returns false for an attempt to add a feature
189 * that would enclose, or be enclosed by, another feature
191 @Test(groups = "Functional")
192 public void testAddNonNestedFeature()
194 FeatureStore fs = new FeatureStore();
196 String type = "Domain";
197 SequenceFeature sf1 = new SequenceFeature(type, type, 10, 20,
199 assertTrue(fs.addNonNestedFeature(sf1));
201 // co-located feature is ok
202 SequenceFeature sf2 = new SequenceFeature(type, type, 10, 20,
204 assertTrue(fs.addNonNestedFeature(sf2));
206 // overlap left is ok
207 SequenceFeature sf3 = new SequenceFeature(type, type, 5, 15, Float.NaN,
209 assertTrue(fs.addNonNestedFeature(sf3));
211 // overlap right is ok
212 SequenceFeature sf4 = new SequenceFeature(type, type, 15, 25,
214 assertTrue(fs.addNonNestedFeature(sf4));
216 // add enclosing feature is not ok
217 SequenceFeature sf5 = new SequenceFeature(type, type, 10, 21,
219 assertFalse(fs.addNonNestedFeature(sf5));
220 SequenceFeature sf6 = new SequenceFeature(type, type, 4, 15, Float.NaN,
222 assertFalse(fs.addNonNestedFeature(sf6));
223 SequenceFeature sf7 = new SequenceFeature(type, type, 1, 50, Float.NaN,
225 assertFalse(fs.addNonNestedFeature(sf7));
227 // add enclosed feature is not ok
228 SequenceFeature sf8 = new SequenceFeature(type, type, 10, 19,
230 assertFalse(fs.addNonNestedFeature(sf8));
231 SequenceFeature sf9 = new SequenceFeature(type, type, 16, 25,
233 assertFalse(fs.addNonNestedFeature(sf9));
234 SequenceFeature sf10 = new SequenceFeature(type, type, 7, 7, Float.NaN,
236 assertFalse(fs.addNonNestedFeature(sf10));
239 @Test(groups = "Functional")
240 public void testGetPositionalFeatures()
242 FeatureStore store = new FeatureStore();
243 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
245 store.addFeature(sf1);
246 // same range, different description
247 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
249 store.addFeature(sf2);
250 // discontiguous range
251 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
253 store.addFeature(sf3);
255 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
257 store.addFeature(sf4);
259 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
261 store.addFeature(sf5);
262 // non-positional feature
263 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
265 store.addFeature(sf6);
267 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
268 18, 45, Float.NaN, null);
269 store.addFeature(sf7);
271 List<SequenceFeature> features = store.getPositionalFeatures();
272 assertEquals(features.size(), 6);
273 assertTrue(features.contains(sf1));
274 assertTrue(features.contains(sf2));
275 assertTrue(features.contains(sf3));
276 assertTrue(features.contains(sf4));
277 assertTrue(features.contains(sf5));
278 assertFalse(features.contains(sf6));
279 assertTrue(features.contains(sf7));
281 features = store.getNonPositionalFeatures();
282 assertEquals(features.size(), 1);
283 assertTrue(features.contains(sf6));
286 @Test(groups = "Functional")
287 public void testDelete()
289 FeatureStore store = new FeatureStore();
290 SequenceFeature sf1 = addFeature(store, 10, 20);
291 assertTrue(store.getPositionalFeatures().contains(sf1));
296 assertTrue(store.delete(sf1));
297 assertTrue(store.getPositionalFeatures().isEmpty());
300 * non-positional feature deletion
302 SequenceFeature sf2 = addFeature(store, 0, 0);
303 assertFalse(store.getPositionalFeatures().contains(sf2));
304 assertTrue(store.getNonPositionalFeatures().contains(sf2));
305 assertTrue(store.delete(sf2));
306 assertTrue(store.getNonPositionalFeatures().isEmpty());
309 * contact feature deletion
311 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
312 23, Float.NaN, null);
313 store.addFeature(sf3);
314 assertEquals(store.getPositionalFeatures().size(), 1);
315 assertTrue(store.getPositionalFeatures().contains(sf3));
316 assertTrue(store.delete(sf3));
317 assertTrue(store.getPositionalFeatures().isEmpty());
320 * nested feature deletion
322 SequenceFeature sf4 = addFeature(store, 20, 30);
323 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
324 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
325 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
326 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
327 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
328 assertEquals(store.getPositionalFeatures().size(), 6);
330 // delete a node with children - they take its place
331 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
332 assertEquals(store.getPositionalFeatures().size(), 5);
333 assertFalse(store.getPositionalFeatures().contains(sf6));
335 // delete a node with no children
336 assertTrue(store.delete(sf7));
337 assertEquals(store.getPositionalFeatures().size(), 4);
338 assertFalse(store.getPositionalFeatures().contains(sf7));
340 // delete root of NCList
341 assertTrue(store.delete(sf5));
342 assertEquals(store.getPositionalFeatures().size(), 3);
343 assertFalse(store.getPositionalFeatures().contains(sf5));
345 // continue the killing fields
346 assertTrue(store.delete(sf4));
347 assertEquals(store.getPositionalFeatures().size(), 2);
348 assertFalse(store.getPositionalFeatures().contains(sf4));
350 assertTrue(store.delete(sf9));
351 assertEquals(store.getPositionalFeatures().size(), 1);
352 assertFalse(store.getPositionalFeatures().contains(sf9));
354 assertTrue(store.delete(sf8));
355 assertTrue(store.getPositionalFeatures().isEmpty());
358 @Test(groups = "Functional")
359 public void testAddFeature()
361 FeatureStore fs = new FeatureStore();
363 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
365 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
368 assertTrue(fs.addFeature(sf1));
369 assertEquals(fs.getFeatureCount(true), 1); // positional
370 assertEquals(fs.getFeatureCount(false), 0); // non-positional
373 * re-adding the same or an identical feature should fail
375 assertFalse(fs.addFeature(sf1));
376 assertEquals(fs.getFeatureCount(true), 1);
377 assertFalse(fs.addFeature(sf2));
378 assertEquals(fs.getFeatureCount(true), 1);
383 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
385 assertTrue(fs.addFeature(sf3));
386 assertEquals(fs.getFeatureCount(true), 1); // positional
387 assertEquals(fs.getFeatureCount(false), 1); // non-positional
388 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
390 assertFalse(fs.addFeature(sf4)); // already stored
391 assertEquals(fs.getFeatureCount(true), 1); // positional
392 assertEquals(fs.getFeatureCount(false), 1); // non-positional
397 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
399 assertTrue(fs.addFeature(sf5));
400 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
401 assertEquals(fs.getFeatureCount(false), 1); // non-positional
402 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
404 assertFalse(fs.addFeature(sf6)); // already stored
405 assertEquals(fs.getFeatureCount(true), 2); // no change
406 assertEquals(fs.getFeatureCount(false), 1); // no change
409 @Test(groups = "Functional")
410 public void testIsEmpty()
412 FeatureStore fs = new FeatureStore();
413 assertTrue(fs.isEmpty());
414 assertEquals(fs.getFeatureCount(true), 0);
419 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
422 assertFalse(fs.isEmpty());
423 assertEquals(fs.getFeatureCount(true), 1);
425 assertTrue(fs.isEmpty());
426 assertEquals(fs.getFeatureCount(true), 0);
429 * non-positional feature
431 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
433 assertFalse(fs.isEmpty());
434 assertEquals(fs.getFeatureCount(false), 1); // non-positional
435 assertEquals(fs.getFeatureCount(true), 0); // positional
437 assertTrue(fs.isEmpty());
438 assertEquals(fs.getFeatureCount(false), 0);
443 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
445 assertFalse(fs.isEmpty());
446 assertEquals(fs.getFeatureCount(true), 1);
448 assertTrue(fs.isEmpty());
449 assertEquals(fs.getFeatureCount(true), 0);
452 * sf2, sf3 added as nested features
454 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
455 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
457 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
462 assertEquals(fs.getFeatureCount(true), 3);
463 assertTrue(fs.delete(sf1));
464 assertEquals(fs.getFeatureCount(true), 2);
465 // FeatureStore should now only contain features in the NCList
466 assertTrue(fs.nonNestedFeatures.isEmpty());
467 assertEquals(fs.nestedFeatures.size(), 2);
468 assertFalse(fs.isEmpty());
469 assertTrue(fs.delete(sf2));
470 assertEquals(fs.getFeatureCount(true), 1);
471 assertFalse(fs.isEmpty());
472 assertTrue(fs.delete(sf3));
473 assertEquals(fs.getFeatureCount(true), 0);
474 assertTrue(fs.isEmpty()); // all gone
477 @Test(groups = "Functional")
478 public void testGetFeatureGroups()
480 FeatureStore fs = new FeatureStore();
481 assertTrue(fs.getFeatureGroups(true).isEmpty());
482 assertTrue(fs.getFeatureGroups(false).isEmpty());
484 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
486 Set<String> groups = fs.getFeatureGroups(true);
487 assertEquals(groups.size(), 1);
488 assertTrue(groups.contains("group1"));
491 * add another feature of the same group, delete one, delete both
493 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
495 groups = fs.getFeatureGroups(true);
496 assertEquals(groups.size(), 1);
497 assertTrue(groups.contains("group1"));
499 groups = fs.getFeatureGroups(true);
500 assertEquals(groups.size(), 1);
501 assertTrue(groups.contains("group1"));
503 groups = fs.getFeatureGroups(true);
504 assertTrue(fs.getFeatureGroups(true).isEmpty());
506 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
508 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
510 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
512 groups = fs.getFeatureGroups(true);
513 assertEquals(groups.size(), 3);
514 assertTrue(groups.contains("group2"));
515 assertTrue(groups.contains("Group2")); // case sensitive
516 assertTrue(groups.contains(null)); // null allowed
517 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
520 groups = fs.getFeatureGroups(true);
521 assertEquals(groups.size(), 2);
522 assertFalse(groups.contains("group2"));
524 groups = fs.getFeatureGroups(true);
525 assertEquals(groups.size(), 1);
526 assertFalse(groups.contains("Group2"));
528 groups = fs.getFeatureGroups(true);
529 assertTrue(groups.isEmpty());
532 * add non-positional feature
534 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
537 groups = fs.getFeatureGroups(false);
538 assertEquals(groups.size(), 1);
539 assertTrue(groups.contains("CathGroup"));
540 assertTrue(fs.delete(sf6));
541 assertTrue(fs.getFeatureGroups(false).isEmpty());
544 @Test(groups = "Functional")
545 public void testGetTotalFeatureLength()
547 FeatureStore fs = new FeatureStore();
548 assertEquals(fs.getTotalFeatureLength(), 0);
550 addFeature(fs, 10, 20); // 11
551 assertEquals(fs.getTotalFeatureLength(), 11);
552 addFeature(fs, 17, 37); // 21
553 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
554 assertEquals(fs.getTotalFeatureLength(), 93);
556 // non-positional features don't count
557 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
560 assertEquals(fs.getTotalFeatureLength(), 93);
562 // contact features count 1
563 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
564 15, 35, 1f, "group1");
566 assertEquals(fs.getTotalFeatureLength(), 94);
568 assertTrue(fs.delete(sf1));
569 assertEquals(fs.getTotalFeatureLength(), 33);
570 assertFalse(fs.delete(sf1));
571 assertEquals(fs.getTotalFeatureLength(), 33);
572 assertTrue(fs.delete(sf2));
573 assertEquals(fs.getTotalFeatureLength(), 33);
574 assertTrue(fs.delete(sf3));
575 assertEquals(fs.getTotalFeatureLength(), 32);
578 @Test(groups = "Functional")
579 public void testGetFeatureLength()
584 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
585 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
588 * non-positional feature
590 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
592 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
595 * contact feature counts 1
597 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
598 14, 28, 1f, "AGroup");
599 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
602 @Test(groups = "Functional")
603 public void testMin()
605 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
606 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
607 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
608 assertEquals(FeatureStore.min(2f, -3f), -3f);
611 @Test(groups = "Functional")
612 public void testMax()
614 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
615 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
616 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
617 assertEquals(FeatureStore.max(2f, -3f), 2f);
620 @Test(groups = "Functional")
621 public void testGetMinimumScore_getMaximumScore()
623 FeatureStore fs = new FeatureStore();
624 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
625 assertEquals(fs.getMaximumScore(true), Float.NaN);
626 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
627 assertEquals(fs.getMaximumScore(false), Float.NaN);
629 // add features with no score
630 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
633 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
636 assertEquals(fs.getMinimumScore(true), Float.NaN);
637 assertEquals(fs.getMaximumScore(true), Float.NaN);
638 assertEquals(fs.getMinimumScore(false), Float.NaN);
639 assertEquals(fs.getMaximumScore(false), Float.NaN);
641 // add positional features with score
642 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
645 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
648 assertEquals(fs.getMinimumScore(true), 1f);
649 assertEquals(fs.getMaximumScore(true), 4f);
650 assertEquals(fs.getMinimumScore(false), Float.NaN);
651 assertEquals(fs.getMaximumScore(false), Float.NaN);
653 // add non-positional features with score
654 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
657 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
660 assertEquals(fs.getMinimumScore(true), 1f);
661 assertEquals(fs.getMaximumScore(true), 4f);
662 assertEquals(fs.getMinimumScore(false), -7f);
663 assertEquals(fs.getMaximumScore(false), 11f);
665 // delete one positional and one non-positional
666 // min-max should be recomputed
667 assertTrue(fs.delete(sf6));
668 assertTrue(fs.delete(sf3));
669 assertEquals(fs.getMinimumScore(true), 4f);
670 assertEquals(fs.getMaximumScore(true), 4f);
671 assertEquals(fs.getMinimumScore(false), 11f);
672 assertEquals(fs.getMaximumScore(false), 11f);
674 // delete remaining features with score
675 assertTrue(fs.delete(sf4));
676 assertTrue(fs.delete(sf5));
677 assertEquals(fs.getMinimumScore(true), Float.NaN);
678 assertEquals(fs.getMaximumScore(true), Float.NaN);
679 assertEquals(fs.getMinimumScore(false), Float.NaN);
680 assertEquals(fs.getMaximumScore(false), Float.NaN);
682 // delete all features
683 assertTrue(fs.delete(sf1));
684 assertTrue(fs.delete(sf2));
685 assertTrue(fs.isEmpty());
686 assertEquals(fs.getMinimumScore(true), Float.NaN);
687 assertEquals(fs.getMaximumScore(true), Float.NaN);
688 assertEquals(fs.getMinimumScore(false), Float.NaN);
689 assertEquals(fs.getMaximumScore(false), Float.NaN);
692 @Test(groups = "Functional")
693 public void testListContains()
695 assertFalse(FeatureStore.listContains(null, null));
696 List<SequenceFeature> features = new ArrayList<SequenceFeature>();
697 assertFalse(FeatureStore.listContains(features, null));
699 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
701 assertFalse(FeatureStore.listContains(null, sf1));
702 assertFalse(FeatureStore.listContains(features, sf1));
705 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
707 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
710 // sf2.equals(sf1) so contains should return true
711 assertTrue(FeatureStore.listContains(features, sf2));
712 assertFalse(FeatureStore.listContains(features, sf3));
715 @Test(groups = "Functional")
716 public void testGetFeaturesForGroup()
718 FeatureStore fs = new FeatureStore();
723 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
724 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
725 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
726 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
729 * sf1: positional feature in the null group
731 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
734 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
735 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
736 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
737 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
738 assertEquals(features.size(), 1);
739 assertTrue(features.contains(sf1));
742 * sf2: non-positional feature in the null group
743 * sf3: positional feature in a non-null group
744 * sf4: non-positional feature in a non-null group
746 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
748 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
750 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
756 features = fs.getFeaturesForGroup(true, null);
757 assertEquals(features.size(), 1);
758 assertTrue(features.contains(sf1));
760 features = fs.getFeaturesForGroup(false, null);
761 assertEquals(features.size(), 1);
762 assertTrue(features.contains(sf2));
764 features = fs.getFeaturesForGroup(true, "Uniprot");
765 assertEquals(features.size(), 1);
766 assertTrue(features.contains(sf3));
768 features = fs.getFeaturesForGroup(false, "Rfam");
769 assertEquals(features.size(), 1);
770 assertTrue(features.contains(sf4));
773 @Test(groups = "Functional")
774 public void testShiftFeatures()
776 FeatureStore fs = new FeatureStore();
777 assertFalse(fs.shiftFeatures(1));
779 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
782 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
785 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
788 // non-positional feature:
789 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
793 * shift features right by 5
795 assertTrue(fs.shiftFeatures(5));
797 // non-positional features untouched:
798 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
799 assertEquals(nonPos.size(), 1);
800 assertTrue(nonPos.contains(sf4));
802 // positional features are replaced
803 List<SequenceFeature> pos = fs.getPositionalFeatures();
804 assertEquals(pos.size(), 3);
805 assertFalse(pos.contains(sf1));
806 assertFalse(pos.contains(sf2));
807 assertFalse(pos.contains(sf3));
808 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
809 assertEquals(pos.get(0).getBegin(), 7);
810 assertEquals(pos.get(0).getEnd(), 10);
811 assertEquals(pos.get(1).getBegin(), 13);
812 assertEquals(pos.get(1).getEnd(), 19);
813 assertEquals(pos.get(2).getBegin(), 28);
814 assertEquals(pos.get(2).getEnd(), 37);
817 * now shift left by 15
818 * feature at [7-10] should be removed
819 * feature at [13-19] should become [1-4]
821 assertTrue(fs.shiftFeatures(-15));
822 pos = fs.getPositionalFeatures();
823 assertEquals(pos.size(), 2);
824 SequenceFeatures.sortFeatures(pos, true);
825 assertEquals(pos.get(0).getBegin(), 1);
826 assertEquals(pos.get(0).getEnd(), 4);
827 assertEquals(pos.get(1).getBegin(), 13);
828 assertEquals(pos.get(1).getEnd(), 22);
831 @Test(groups = "Functional")
832 public void testDelete_readd()
835 * add a feature and a nested feature
837 FeatureStore store = new FeatureStore();
838 SequenceFeature sf1 = addFeature(store, 10, 20);
839 // sf2 is nested in sf1 so will be stored in nestedFeatures
840 SequenceFeature sf2 = addFeature(store, 12, 14);
841 List<SequenceFeature> features = store.getPositionalFeatures();
842 assertEquals(features.size(), 2);
843 assertTrue(features.contains(sf1));
844 assertTrue(features.contains(sf2));
845 assertTrue(store.nonNestedFeatures.contains(sf1));
846 assertTrue(store.nestedFeatures.contains(sf2));
849 * delete the first feature
851 assertTrue(store.delete(sf1));
852 features = store.getPositionalFeatures();
853 assertFalse(features.contains(sf1));
854 assertTrue(features.contains(sf2));
857 * re-add the 'nested' feature; is it now duplicated?
859 store.addFeature(sf2);
860 features = store.getPositionalFeatures();
861 assertEquals(features.size(), 1);
862 assertTrue(features.contains(sf2));
865 @Test(groups = "Functional")
866 public void testContains()
868 FeatureStore fs = new FeatureStore();
869 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
870 Float.NaN, "group1");
871 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
872 Float.NaN, "group2");
873 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
875 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
877 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
878 Float.NaN, "group1");
879 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
880 Float.NaN, "group2");
885 assertTrue(fs.contains(sf1)); // positional feature
886 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
887 assertFalse(fs.contains(sf2)); // different group
888 assertTrue(fs.contains(sf3)); // non-positional
889 assertTrue(fs.contains(new SequenceFeature(sf3)));
890 assertFalse(fs.contains(sf4)); // different score
891 assertTrue(fs.contains(sf5)); // contact feature
892 assertTrue(fs.contains(new SequenceFeature(sf5)));
893 assertFalse(fs.contains(sf6)); // different group
896 * add a nested feature
898 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
899 Float.NaN, "group1");
901 assertTrue(fs.contains(sf7));
902 assertTrue(fs.contains(new SequenceFeature(sf7)));
905 * delete the outer (enclosing, non-nested) feature
908 assertFalse(fs.contains(sf1));
909 assertTrue(fs.contains(sf7));