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.Collection;
12 import java.util.List;
15 import org.testng.annotations.Test;
17 import junit.extensions.PA;
19 public class FeatureStoreTest
21 private FeatureStore newFeatureStore()
23 return new FeatureStore();
26 @Test(groups = "Functional")
27 public void testFindFeatures_nonNested()
29 FeatureStore fs = newFeatureStore();
30 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
32 // same range different description
33 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
34 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
35 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
37 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
38 assertTrue(overlaps.isEmpty());
40 overlaps = fs.findOverlappingFeatures(8, 10);
41 assertEquals(overlaps.size(), 2);
42 assertEquals(overlaps.get(0).getEnd(), 20);
43 assertEquals(overlaps.get(1).getEnd(), 20);
45 overlaps = fs.findOverlappingFeatures(12, 16);
46 assertEquals(overlaps.size(), 3);
47 assertEquals(overlaps.get(0).getEnd(), 20);
48 assertEquals(overlaps.get(1).getEnd(), 20);
49 assertEquals(overlaps.get(2).getEnd(), 25);
51 overlaps = fs.findOverlappingFeatures(33, 33);
52 assertEquals(overlaps.size(), 1);
53 assertEquals(overlaps.get(0).getEnd(), 35);
56 @Test(groups = "Functional")
57 public void testFindFeatures_nested()
59 FeatureStore fs = newFeatureStore();
60 SequenceFeature sf1 = addFeature(fs, 10, 50);
61 SequenceFeature sf2 = addFeature(fs, 10, 40);
62 SequenceFeature sf3 = addFeature(fs, 20, 30);
63 // fudge feature at same location but different group (so is added)
64 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
67 SequenceFeature sf5 = addFeature(fs, 35, 36);
69 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
70 assertTrue(overlaps.isEmpty());
72 overlaps = fs.findOverlappingFeatures(10, 15);
73 assertEquals(overlaps.size(), 2);
74 assertTrue(overlaps.contains(sf1));
75 assertTrue(overlaps.contains(sf2));
77 overlaps = fs.findOverlappingFeatures(45, 60);
78 assertEquals(overlaps.size(), 1);
79 assertTrue(overlaps.contains(sf1));
81 overlaps = fs.findOverlappingFeatures(32, 38);
82 assertEquals(overlaps.size(), 3);
83 assertTrue(overlaps.contains(sf1));
84 assertTrue(overlaps.contains(sf2));
85 assertTrue(overlaps.contains(sf5));
87 overlaps = fs.findOverlappingFeatures(15, 25);
88 assertEquals(overlaps.size(), 4);
89 assertTrue(overlaps.contains(sf1));
90 assertTrue(overlaps.contains(sf2));
91 assertTrue(overlaps.contains(sf3));
92 assertTrue(overlaps.contains(sf4));
95 @Test(groups = "Functional")
96 public void testFindFeatures_mixed()
98 FeatureStore fs = newFeatureStore();
99 SequenceFeature sf1 = addFeature(fs, 10, 50);
100 SequenceFeature sf2 = addFeature(fs, 1, 15);
101 SequenceFeature sf3 = addFeature(fs, 20, 30);
102 SequenceFeature sf4 = addFeature(fs, 40, 100);
103 SequenceFeature sf5 = addFeature(fs, 60, 100);
104 SequenceFeature sf6 = addFeature(fs, 70, 70);
106 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
107 assertTrue(overlaps.isEmpty());
109 overlaps = fs.findOverlappingFeatures(1, 9);
110 assertEquals(overlaps.size(), 1);
111 assertTrue(overlaps.contains(sf2));
113 overlaps = fs.findOverlappingFeatures(5, 18);
114 assertEquals(overlaps.size(), 2);
115 assertTrue(overlaps.contains(sf1));
116 assertTrue(overlaps.contains(sf2));
118 overlaps = fs.findOverlappingFeatures(30, 40);
119 assertEquals(overlaps.size(), 3);
120 assertTrue(overlaps.contains(sf1));
121 assertTrue(overlaps.contains(sf3));
122 assertTrue(overlaps.contains(sf4));
124 overlaps = fs.findOverlappingFeatures(80, 90);
125 assertEquals(overlaps.size(), 2);
126 assertTrue(overlaps.contains(sf4));
127 assertTrue(overlaps.contains(sf5));
129 overlaps = fs.findOverlappingFeatures(68, 70);
130 assertEquals(overlaps.size(), 3);
131 assertTrue(overlaps.contains(sf4));
132 assertTrue(overlaps.contains(sf5));
133 assertTrue(overlaps.contains(sf6));
137 * Helper method to add a feature of no particular type
144 SequenceFeature addFeature(FeatureStore fs, int from, int to)
146 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
152 @Test(groups = "Functional")
153 public void testFindFeatures_contactFeatures()
155 FeatureStore fs = newFeatureStore();
157 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
158 20, Float.NaN, null);
162 * neither contact point in range
164 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
165 assertTrue(overlaps.isEmpty());
168 * neither contact point in range
170 overlaps = fs.findOverlappingFeatures(11, 19);
171 assertTrue(overlaps.isEmpty());
174 * first contact point in range
176 overlaps = fs.findOverlappingFeatures(5, 15);
177 assertEquals(overlaps.size(), 1);
178 assertTrue(overlaps.contains(sf));
181 * second contact point in range
183 overlaps = fs.findOverlappingFeatures(15, 25);
184 assertEquals(overlaps.size(), 1);
185 assertTrue(overlaps.contains(sf));
188 * both contact points in range
190 overlaps = fs.findOverlappingFeatures(5, 25);
191 assertEquals(overlaps.size(), 1);
192 assertTrue(overlaps.contains(sf));
195 @Test(groups = "Functional")
196 public void testGetPositionalFeatures()
198 FeatureStore store = newFeatureStore();
199 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
201 store.addFeature(sf1);
202 // same range, different description
203 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
205 store.addFeature(sf2);
206 // discontiguous range
207 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
209 store.addFeature(sf3);
211 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
213 store.addFeature(sf4);
215 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
217 store.addFeature(sf5);
218 // non-positional feature
219 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
221 store.addFeature(sf6);
223 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
224 18, 45, Float.NaN, null);
225 store.addFeature(sf7);
227 List<SequenceFeature> features = store.getPositionalFeatures();
228 assertEquals(features.size(), 6);
229 assertTrue(features.contains(sf1));
230 assertTrue(features.contains(sf2));
231 assertTrue(features.contains(sf3));
232 assertTrue(features.contains(sf4));
233 assertTrue(features.contains(sf5));
234 assertFalse(features.contains(sf6));
235 assertTrue(features.contains(sf7));
237 features = store.getNonPositionalFeatures();
238 assertEquals(features.size(), 1);
239 assertTrue(features.contains(sf6));
242 @Test(groups = "Functional")
243 public void testDelete()
245 FeatureStore store = newFeatureStore();
246 SequenceFeature sf1 = addFeature(store, 10, 20);
247 assertTrue(store.getPositionalFeatures().contains(sf1));
252 assertTrue(store.delete(sf1));
253 assertTrue(store.getPositionalFeatures().isEmpty());
256 * non-positional feature deletion
258 SequenceFeature sf2 = addFeature(store, 0, 0);
259 assertFalse(store.getPositionalFeatures().contains(sf2));
260 assertTrue(store.getNonPositionalFeatures().contains(sf2));
261 assertTrue(store.delete(sf2));
262 assertTrue(store.getNonPositionalFeatures().isEmpty());
265 * contact feature deletion
267 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
268 23, Float.NaN, null);
269 store.addFeature(sf3);
270 assertEquals(store.getPositionalFeatures().size(), 1);
271 assertTrue(store.getPositionalFeatures().contains(sf3));
272 assertTrue(store.delete(sf3));
273 assertTrue(store.getPositionalFeatures().isEmpty());
276 * nested feature deletion
278 SequenceFeature sf4 = addFeature(store, 20, 30);
279 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
280 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
281 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
282 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
283 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
284 assertEquals(store.getPositionalFeatures().size(), 6);
286 // delete a node with children - they take its place
287 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
288 assertEquals(store.getPositionalFeatures().size(), 5);
289 assertFalse(store.getPositionalFeatures().contains(sf6));
291 // delete a node with no children
292 assertTrue(store.delete(sf7));
293 assertEquals(store.getPositionalFeatures().size(), 4);
294 assertFalse(store.getPositionalFeatures().contains(sf7));
296 // delete root of NCList
297 assertTrue(store.delete(sf5));
298 assertEquals(store.getPositionalFeatures().size(), 3);
299 assertFalse(store.getPositionalFeatures().contains(sf5));
301 // continue the killing fields
302 assertTrue(store.delete(sf4));
303 assertEquals(store.getPositionalFeatures().size(), 2);
304 assertFalse(store.getPositionalFeatures().contains(sf4));
306 assertTrue(store.delete(sf9));
307 assertEquals(store.getPositionalFeatures().size(), 1);
308 assertFalse(store.getPositionalFeatures().contains(sf9));
310 assertTrue(store.delete(sf8));
311 assertTrue(store.getPositionalFeatures().isEmpty());
314 @Test(groups = "Functional")
315 public void testAddFeature()
317 FeatureStore fs = newFeatureStore();
319 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
321 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
324 assertTrue(fs.addFeature(sf1));
325 assertEquals(fs.getFeatureCount(true), 1); // positional
326 assertEquals(fs.getFeatureCount(false), 0); // non-positional
329 * re-adding the same or an identical feature should fail
331 assertFalse(fs.addFeature(sf1));
332 assertEquals(fs.getFeatureCount(true), 1);
333 assertFalse(fs.addFeature(sf2));
334 assertEquals(fs.getFeatureCount(true), 1);
339 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
341 assertTrue(fs.addFeature(sf3));
342 assertEquals(fs.getFeatureCount(true), 1); // positional
343 assertEquals(fs.getFeatureCount(false), 1); // non-positional
344 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
346 assertFalse(fs.addFeature(sf4)); // already stored
347 assertEquals(fs.getFeatureCount(true), 1); // positional
348 assertEquals(fs.getFeatureCount(false), 1); // non-positional
353 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
355 assertTrue(fs.addFeature(sf5));
356 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
357 assertEquals(fs.getFeatureCount(false), 1); // non-positional
358 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
360 assertFalse(fs.addFeature(sf6)); // already stored
361 assertEquals(fs.getFeatureCount(true), 2); // no change
362 assertEquals(fs.getFeatureCount(false), 1); // no change
365 @Test(groups = "Functional")
366 public void testIsEmpty()
368 FeatureStore fs = newFeatureStore();
369 assertTrue(fs.isEmpty());
370 assertEquals(fs.getFeatureCount(true), 0);
375 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
378 assertFalse(fs.isEmpty());
379 assertEquals(fs.getFeatureCount(true), 1);
381 assertTrue(fs.isEmpty());
382 assertEquals(fs.getFeatureCount(true), 0);
385 * non-positional feature
387 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
389 assertFalse(fs.isEmpty());
390 assertEquals(fs.getFeatureCount(false), 1); // non-positional
391 assertEquals(fs.getFeatureCount(true), 0); // positional
393 assertTrue(fs.isEmpty());
394 assertEquals(fs.getFeatureCount(false), 0);
399 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
401 assertFalse(fs.isEmpty());
402 assertEquals(fs.getFeatureCount(true), 1);
404 assertTrue(fs.isEmpty());
405 assertEquals(fs.getFeatureCount(true), 0);
408 * sf2, sf3 added as nested features
410 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
411 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
413 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
418 assertEquals(fs.getFeatureCount(true), 3);
419 assertTrue(fs.delete(sf1));
420 assertEquals(fs.getFeatureCount(true), 2);
421 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
422 .getValue(fs, "features");
423 assertEquals(intervalStore.size(), 2);
424 assertFalse(fs.isEmpty());
425 assertTrue(fs.delete(sf2));
426 assertEquals(fs.getFeatureCount(true), 1);
427 assertFalse(fs.isEmpty());
428 assertTrue(fs.delete(sf3));
429 assertEquals(fs.getFeatureCount(true), 0);
430 assertTrue(fs.isEmpty()); // all gone
433 @Test(groups = "Functional")
434 public void testGetFeatureGroups()
436 FeatureStore fs = newFeatureStore();
437 assertTrue(fs.getFeatureGroups(true).isEmpty());
438 assertTrue(fs.getFeatureGroups(false).isEmpty());
440 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
442 Set<String> groups = fs.getFeatureGroups(true);
443 assertEquals(groups.size(), 1);
444 assertTrue(groups.contains("group1"));
447 * add another feature of the same group, delete one, delete both
449 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
451 groups = fs.getFeatureGroups(true);
452 assertEquals(groups.size(), 1);
453 assertTrue(groups.contains("group1"));
455 groups = fs.getFeatureGroups(true);
456 assertEquals(groups.size(), 1);
457 assertTrue(groups.contains("group1"));
459 groups = fs.getFeatureGroups(true);
460 assertTrue(fs.getFeatureGroups(true).isEmpty());
462 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
464 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
466 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
468 groups = fs.getFeatureGroups(true);
469 assertEquals(groups.size(), 3);
470 assertTrue(groups.contains("group2"));
471 assertTrue(groups.contains("Group2")); // case sensitive
472 assertTrue(groups.contains(null)); // null allowed
473 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
476 groups = fs.getFeatureGroups(true);
477 assertEquals(groups.size(), 2);
478 assertFalse(groups.contains("group2"));
480 groups = fs.getFeatureGroups(true);
481 assertEquals(groups.size(), 1);
482 assertFalse(groups.contains("Group2"));
484 groups = fs.getFeatureGroups(true);
485 assertTrue(groups.isEmpty());
488 * add non-positional feature
490 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
493 groups = fs.getFeatureGroups(false);
494 assertEquals(groups.size(), 1);
495 assertTrue(groups.contains("CathGroup"));
496 assertTrue(fs.delete(sf6));
497 assertTrue(fs.getFeatureGroups(false).isEmpty());
500 @Test(groups = "Functional")
501 public void testGetTotalFeatureLength()
503 FeatureStore fs = newFeatureStore();
504 assertEquals(fs.getTotalFeatureLength(), 0);
506 addFeature(fs, 10, 20); // 11
507 assertEquals(fs.getTotalFeatureLength(), 11);
508 addFeature(fs, 17, 37); // 21
509 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
510 assertEquals(fs.getTotalFeatureLength(), 93);
512 // non-positional features don't count
513 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
516 assertEquals(fs.getTotalFeatureLength(), 93);
518 // contact features count 1
519 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
520 15, 35, 1f, "group1");
522 assertEquals(fs.getTotalFeatureLength(), 94);
524 assertTrue(fs.delete(sf1));
525 assertEquals(fs.getTotalFeatureLength(), 33);
526 assertFalse(fs.delete(sf1));
527 assertEquals(fs.getTotalFeatureLength(), 33);
528 assertTrue(fs.delete(sf2));
529 assertEquals(fs.getTotalFeatureLength(), 33);
530 assertTrue(fs.delete(sf3));
531 assertEquals(fs.getTotalFeatureLength(), 32);
534 @Test(groups = "Functional")
535 public void testGetFeatureLength()
540 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
541 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
544 * non-positional feature
546 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
548 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
551 * contact feature counts 1
553 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
554 14, 28, 1f, "AGroup");
555 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
558 @Test(groups = "Functional")
559 public void testMin()
561 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
562 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
563 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
564 assertEquals(FeatureStore.min(2f, -3f), -3f);
567 @Test(groups = "Functional")
568 public void testMax()
570 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
571 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
572 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
573 assertEquals(FeatureStore.max(2f, -3f), 2f);
576 @Test(groups = "Functional")
577 public void testGetMinimumScore_getMaximumScore()
579 FeatureStore fs = newFeatureStore();
580 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
581 assertEquals(fs.getMaximumScore(true), Float.NaN);
582 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
583 assertEquals(fs.getMaximumScore(false), Float.NaN);
585 // add features with no score
586 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
589 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
592 assertEquals(fs.getMinimumScore(true), Float.NaN);
593 assertEquals(fs.getMaximumScore(true), Float.NaN);
594 assertEquals(fs.getMinimumScore(false), Float.NaN);
595 assertEquals(fs.getMaximumScore(false), Float.NaN);
597 // add positional features with score
598 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
601 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
604 assertEquals(fs.getMinimumScore(true), 1f);
605 assertEquals(fs.getMaximumScore(true), 4f);
606 assertEquals(fs.getMinimumScore(false), Float.NaN);
607 assertEquals(fs.getMaximumScore(false), Float.NaN);
609 // add non-positional features with score
610 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
613 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
616 assertEquals(fs.getMinimumScore(true), 1f);
617 assertEquals(fs.getMaximumScore(true), 4f);
618 assertEquals(fs.getMinimumScore(false), -7f);
619 assertEquals(fs.getMaximumScore(false), 11f);
621 // delete one positional and one non-positional
622 // min-max should be recomputed
623 assertTrue(fs.delete(sf6));
624 assertTrue(fs.delete(sf3));
625 assertEquals(fs.getMinimumScore(true), 4f);
626 assertEquals(fs.getMaximumScore(true), 4f);
627 assertEquals(fs.getMinimumScore(false), 11f);
628 assertEquals(fs.getMaximumScore(false), 11f);
630 // delete remaining features with score
631 assertTrue(fs.delete(sf4));
632 assertTrue(fs.delete(sf5));
633 assertEquals(fs.getMinimumScore(true), Float.NaN);
634 assertEquals(fs.getMaximumScore(true), Float.NaN);
635 assertEquals(fs.getMinimumScore(false), Float.NaN);
636 assertEquals(fs.getMaximumScore(false), Float.NaN);
638 // delete all features
639 assertTrue(fs.delete(sf1));
640 assertTrue(fs.delete(sf2));
641 assertTrue(fs.isEmpty());
642 assertEquals(fs.getMinimumScore(true), Float.NaN);
643 assertEquals(fs.getMaximumScore(true), Float.NaN);
644 assertEquals(fs.getMinimumScore(false), Float.NaN);
645 assertEquals(fs.getMaximumScore(false), Float.NaN);
648 @Test(groups = "Functional")
649 public void testListContains()
651 FeatureStore featureStore = newFeatureStore();
652 assertFalse(featureStore.listContains(null, null));
653 List<SequenceFeature> features = new ArrayList<>();
654 assertFalse(featureStore.listContains(features, null));
656 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
658 assertFalse(featureStore.listContains(null, sf1));
659 assertFalse(featureStore.listContains(features, sf1));
662 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
664 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
667 // sf2.equals(sf1) so contains should return true
668 assertTrue(featureStore.listContains(features, sf2));
669 assertFalse(featureStore.listContains(features, sf3));
672 @Test(groups = "Functional")
673 public void testGetFeaturesForGroup()
675 FeatureStore fs = newFeatureStore();
680 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
681 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
682 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
683 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
686 * sf1: positional feature in the null group
688 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
691 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
692 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
693 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
694 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
695 assertEquals(features.size(), 1);
696 assertTrue(features.contains(sf1));
699 * sf2: non-positional feature in the null group
700 * sf3: positional feature in a non-null group
701 * sf4: non-positional feature in a non-null group
703 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
705 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
707 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
713 features = fs.getFeaturesForGroup(true, null);
714 assertEquals(features.size(), 1);
715 assertTrue(features.contains(sf1));
717 features = fs.getFeaturesForGroup(false, null);
718 assertEquals(features.size(), 1);
719 assertTrue(features.contains(sf2));
721 features = fs.getFeaturesForGroup(true, "Uniprot");
722 assertEquals(features.size(), 1);
723 assertTrue(features.contains(sf3));
725 features = fs.getFeaturesForGroup(false, "Rfam");
726 assertEquals(features.size(), 1);
727 assertTrue(features.contains(sf4));
730 @Test(groups = "Functional")
731 public void testShiftFeatures()
733 FeatureStore fs = newFeatureStore();
734 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
736 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
739 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
742 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
745 // non-positional feature:
746 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
750 * shift all features right by 5
752 assertTrue(fs.shiftFeatures(0, 5));
754 // non-positional features untouched:
755 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
756 assertEquals(nonPos.size(), 1);
757 assertTrue(nonPos.contains(sf4));
759 // positional features are replaced
760 List<SequenceFeature> pos = fs.getPositionalFeatures();
761 assertEquals(pos.size(), 3);
762 assertFalse(pos.contains(sf1));
763 assertFalse(pos.contains(sf2));
764 assertFalse(pos.contains(sf3));
765 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
766 assertEquals(pos.get(0).getBegin(), 7);
767 assertEquals(pos.get(0).getEnd(), 10);
768 assertEquals(pos.get(1).getBegin(), 13);
769 assertEquals(pos.get(1).getEnd(), 19);
770 assertEquals(pos.get(2).getBegin(), 28);
771 assertEquals(pos.get(2).getEnd(), 37);
774 * now shift left by 15
775 * feature at [7-10] should be removed
776 * feature at [13-19] should become [1-4]
778 assertTrue(fs.shiftFeatures(0, -15));
779 pos = fs.getPositionalFeatures();
780 assertEquals(pos.size(), 2);
781 SequenceFeatures.sortFeatures(pos, true);
782 assertEquals(pos.get(0).getBegin(), 1);
783 assertEquals(pos.get(0).getEnd(), 4);
784 assertEquals(pos.get(1).getBegin(), 13);
785 assertEquals(pos.get(1).getEnd(), 22);
788 * shift right by 4 from position 2 onwards
789 * feature at [1-4] unchanged, feature at [13-22] shifts
791 assertTrue(fs.shiftFeatures(2, 4));
792 pos = fs.getPositionalFeatures();
793 assertEquals(pos.size(), 2);
794 SequenceFeatures.sortFeatures(pos, true);
795 assertEquals(pos.get(0).getBegin(), 1);
796 assertEquals(pos.get(0).getEnd(), 4);
797 assertEquals(pos.get(1).getBegin(), 17);
798 assertEquals(pos.get(1).getEnd(), 26);
801 * shift right by 4 from position 18 onwards
802 * should be no change
804 SequenceFeature f1 = pos.get(0);
805 SequenceFeature f2 = pos.get(1);
806 assertFalse(fs.shiftFeatures(18, 4)); // no update
807 pos = fs.getPositionalFeatures();
808 assertEquals(pos.size(), 2);
809 SequenceFeatures.sortFeatures(pos, true);
810 assertSame(pos.get(0), f1);
811 assertSame(pos.get(1), f2);
814 @Test(groups = "Functional")
815 public void testDelete_readd()
818 * add a feature and a nested feature
820 FeatureStore store = newFeatureStore();
821 SequenceFeature sf1 = addFeature(store, 10, 20);
822 // sf2 is nested in sf1 so will be stored in nestedFeatures
823 SequenceFeature sf2 = addFeature(store, 12, 14);
824 List<SequenceFeature> features = store.getPositionalFeatures();
825 assertEquals(features.size(), 2);
826 assertTrue(features.contains(sf1));
827 assertTrue(features.contains(sf2));
828 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
829 .getValue(store, "features");
830 assertTrue(intervalStore.contains(sf1));
831 assertTrue(intervalStore.contains(sf2));
834 * delete the first feature
836 assertTrue(store.delete(sf1));
837 features = store.getPositionalFeatures();
838 assertFalse(features.contains(sf1));
839 assertTrue(features.contains(sf2));
842 * re-add the 'nested' feature; is it now duplicated?
844 store.addFeature(sf2);
845 features = store.getPositionalFeatures();
846 assertEquals(features.size(), 1);
847 assertTrue(features.contains(sf2));
850 @Test(groups = "Functional")
851 public void testContains()
853 FeatureStore fs = newFeatureStore();
854 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
855 Float.NaN, "group1");
856 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
857 Float.NaN, "group2");
858 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
860 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
862 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
863 Float.NaN, "group1");
864 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
865 Float.NaN, "group2");
870 assertTrue(fs.contains(sf1)); // positional feature
871 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
872 assertFalse(fs.contains(sf2)); // different group
873 assertTrue(fs.contains(sf3)); // non-positional
874 assertTrue(fs.contains(new SequenceFeature(sf3)));
875 assertFalse(fs.contains(sf4)); // different score
876 assertTrue(fs.contains(sf5)); // contact feature
877 assertTrue(fs.contains(new SequenceFeature(sf5)));
878 assertFalse(fs.contains(sf6)); // different group
881 * add a nested feature
883 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
884 Float.NaN, "group1");
886 assertTrue(fs.contains(sf7));
887 assertTrue(fs.contains(new SequenceFeature(sf7)));
890 * delete the outer (enclosing, non-nested) feature
893 assertFalse(fs.contains(sf1));
894 assertTrue(fs.contains(sf7));
897 @Test(groups = "Functional")
898 public void testFindFeatures_withResultList()
900 FeatureStore fs = newFeatureStore();
901 SequenceFeature sf1 = addFeature(fs, 10, 50);
902 SequenceFeature sf2 = addFeature(fs, 150, 250);
904 List<SequenceFeature> overlaps = new ArrayList<>();
905 List<SequenceFeature> result = fs.findOverlappingFeatures(200, 200,
907 assertSame(result, overlaps);
908 assertEquals(result.size(), 1);
909 assertTrue(result.contains(sf2));
910 assertFalse(result.contains(sf1));
913 * if no list supplied, method creates one
915 result = fs.findOverlappingFeatures(200, 200, null);
916 assertEquals(result.size(), 1);
917 assertTrue(result.contains(sf2));
918 assertFalse(result.contains(sf1));