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;
9 import jalview.datamodel.features.FeatureStore.IntervalStoreType;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
16 import org.testng.annotations.Test;
18 import junit.extensions.PA;
21 * Tests that exercise the 'linked list' version of IntervalStore
23 public class FeatureStoreLinkedTest
25 private FeatureStore newFeatureStore()
27 return new FeatureStore(IntervalStoreType.INTERVAL_STORE_LINKED_LIST);
30 @Test(groups = "Functional")
31 public void testFindFeatures_nonNested()
33 FeatureStore fs = newFeatureStore();
34 SequenceFeature sf0 = new SequenceFeature("", "", 10, 20, Float.NaN,
37 // same range different description
38 SequenceFeature sf1 = new SequenceFeature("", "desc", 10, 20, Float.NaN, null);
40 SequenceFeature sf2 = new SequenceFeature("", "", 15, 25, Float.NaN, null);
42 SequenceFeature sf3 = new SequenceFeature("", "", 20, 35, Float.NaN, null);
45 List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
46 assertTrue(overlaps.isEmpty());
48 overlaps = fs.findFeatures(8, 10);
49 assertEquals(overlaps.size(), 2);
50 assertTrue(overlaps.contains(sf0));
51 assertTrue(overlaps.contains(sf1));
53 overlaps = fs.findFeatures(12, 16);
54 assertEquals(overlaps.size(), 3);
55 assertTrue(overlaps.contains(sf0));
56 assertTrue(overlaps.contains(sf1));
57 assertTrue(overlaps.contains(sf2));
59 overlaps = fs.findFeatures(33, 33);
60 assertEquals(overlaps.size(), 1);
61 assertTrue(overlaps.contains(sf3));
64 @Test(groups = "Functional")
65 public void testFindFeatures_nested()
67 FeatureStore fs = newFeatureStore();
68 SequenceFeature sf1 = addFeature(fs, 10, 50);
69 SequenceFeature sf2 = addFeature(fs, 10, 40);
70 SequenceFeature sf3 = addFeature(fs, 20, 30);
71 // fudge feature at same location but different group (so is added)
72 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
75 SequenceFeature sf5 = addFeature(fs, 35, 36);
77 List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
78 assertTrue(overlaps.isEmpty());
80 overlaps = fs.findFeatures(10, 15);
81 assertEquals(overlaps.size(), 2);
82 assertTrue(overlaps.contains(sf1));
83 assertTrue(overlaps.contains(sf2));
85 overlaps = fs.findFeatures(45, 60);
86 assertEquals(overlaps.size(), 1);
87 assertTrue(overlaps.contains(sf1));
89 overlaps = fs.findFeatures(32, 38);
90 assertEquals(overlaps.size(), 3);
91 assertTrue(overlaps.contains(sf1));
92 assertTrue(overlaps.contains(sf2));
93 assertTrue(overlaps.contains(sf5));
95 overlaps = fs.findFeatures(15, 25);
96 assertEquals(overlaps.size(), 4);
97 assertTrue(overlaps.contains(sf1));
98 assertTrue(overlaps.contains(sf2));
99 assertTrue(overlaps.contains(sf3));
100 assertTrue(overlaps.contains(sf4));
103 @Test(groups = "Functional")
104 public void testFindFeatures_mixed()
106 FeatureStore fs = newFeatureStore();
107 SequenceFeature sf1 = addFeature(fs, 10, 50);
108 SequenceFeature sf2 = addFeature(fs, 1, 15);
109 SequenceFeature sf3 = addFeature(fs, 20, 30);
110 SequenceFeature sf4 = addFeature(fs, 40, 100);
111 SequenceFeature sf5 = addFeature(fs, 60, 100);
112 SequenceFeature sf6 = addFeature(fs, 70, 70);
114 List<SequenceFeature> overlaps = fs.findFeatures(200, 200);
115 assertTrue(overlaps.isEmpty());
117 overlaps = fs.findFeatures(1, 9);
118 assertEquals(overlaps.size(), 1);
119 assertTrue(overlaps.contains(sf2));
121 overlaps = fs.findFeatures(5, 18);
122 assertEquals(overlaps.size(), 2);
123 assertTrue(overlaps.contains(sf1));
124 assertTrue(overlaps.contains(sf2));
126 overlaps = fs.findFeatures(30, 40);
127 assertEquals(overlaps.size(), 3);
128 assertTrue(overlaps.contains(sf1));
129 assertTrue(overlaps.contains(sf3));
130 assertTrue(overlaps.contains(sf4));
132 overlaps = fs.findFeatures(80, 90);
133 assertEquals(overlaps.size(), 2);
134 assertTrue(overlaps.contains(sf4));
135 assertTrue(overlaps.contains(sf5));
137 overlaps = fs.findFeatures(68, 70);
138 assertEquals(overlaps.size(), 3);
139 assertTrue(overlaps.contains(sf4));
140 assertTrue(overlaps.contains(sf5));
141 assertTrue(overlaps.contains(sf6));
145 * Helper method to add a feature of no particular type
152 SequenceFeature addFeature(FeatureStore fs, int from, int to)
154 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
160 @Test(groups = "Functional")
161 public void testFindFeatures_contactFeatures()
163 FeatureStore fs = newFeatureStore();
165 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
166 20, Float.NaN, null);
170 * neither contact point in range
172 List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
173 assertTrue(overlaps.isEmpty());
176 * neither contact point in range
178 overlaps = fs.findFeatures(11, 19);
179 assertTrue(overlaps.isEmpty());
182 * first contact point in range
184 overlaps = fs.findFeatures(5, 15);
185 assertEquals(overlaps.size(), 1);
186 assertTrue(overlaps.contains(sf));
189 * second contact point in range
191 overlaps = fs.findFeatures(15, 25);
192 assertEquals(overlaps.size(), 1);
193 assertTrue(overlaps.contains(sf));
196 * both contact points in range
198 overlaps = fs.findFeatures(5, 25);
199 assertEquals(overlaps.size(), 1);
200 assertTrue(overlaps.contains(sf));
203 @Test(groups = "Functional")
204 public void testGetPositionalFeatures()
206 FeatureStore store = newFeatureStore();
207 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
209 store.addFeature(sf1);
210 // same range, different description
211 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
213 store.addFeature(sf2);
214 // discontiguous range
215 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
217 store.addFeature(sf3);
219 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
221 store.addFeature(sf4);
223 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
225 store.addFeature(sf5);
226 // non-positional feature
227 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
229 store.addFeature(sf6);
231 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
232 18, 45, Float.NaN, null);
233 store.addFeature(sf7);
235 List<SequenceFeature> features = store.getPositionalFeatures();
236 assertEquals(features.size(), 6);
237 assertTrue(features.contains(sf1));
238 assertTrue(features.contains(sf2));
239 assertTrue(features.contains(sf3));
240 assertTrue(features.contains(sf4));
241 assertTrue(features.contains(sf5));
242 assertFalse(features.contains(sf6));
243 assertTrue(features.contains(sf7));
245 features = store.getNonPositionalFeatures();
246 assertEquals(features.size(), 1);
247 assertTrue(features.contains(sf6));
250 @Test(groups = "Functional")
251 public void testDelete()
253 FeatureStore store = newFeatureStore();
254 SequenceFeature sf1 = addFeature(store, 10, 20);
255 assertTrue(store.getPositionalFeatures().contains(sf1));
260 assertTrue(store.delete(sf1));
261 assertTrue(store.getPositionalFeatures().isEmpty());
264 * non-positional feature deletion
266 SequenceFeature sf2 = addFeature(store, 0, 0);
267 assertFalse(store.getPositionalFeatures().contains(sf2));
268 assertTrue(store.getNonPositionalFeatures().contains(sf2));
269 assertTrue(store.delete(sf2));
270 assertTrue(store.getNonPositionalFeatures().isEmpty());
273 * contact feature deletion
275 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
276 23, Float.NaN, null);
277 store.addFeature(sf3);
278 assertEquals(store.getPositionalFeatures().size(), 1);
279 assertTrue(store.getPositionalFeatures().contains(sf3));
280 assertTrue(store.delete(sf3));
281 assertTrue(store.getPositionalFeatures().isEmpty());
284 * nested feature deletion
286 SequenceFeature sf4 = addFeature(store, 20, 30);
287 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
288 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
289 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
290 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
291 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
293 // SequenceFeature sf4 = addFeature(store, 20, 30);
294 //// SequenceFeature sf5 = addFeature(store, 22, 26);
295 ////// SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
296 //////// SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
297 //////// SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
298 ////// SequenceFeature sf7 = addFeature(store, 25, 25); // child of sf5
300 assertEquals(store.getPositionalFeatures().size(), 6);
302 // delete a node with children - they take its place
303 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
304 assertEquals(store.getPositionalFeatures().size(), 5);
305 assertFalse(store.getPositionalFeatures().contains(sf6));
307 // delete a node with no children
308 assertTrue(store.delete(sf7));
309 assertEquals(store.getPositionalFeatures().size(), 4);
310 assertFalse(store.getPositionalFeatures().contains(sf7));
312 // delete root of NCList
313 assertTrue(store.delete(sf5));
314 assertEquals(store.getPositionalFeatures().size(), 3);
315 assertFalse(store.getPositionalFeatures().contains(sf5));
317 // continue the killing fields
318 assertTrue(store.delete(sf4));
319 assertEquals(store.getPositionalFeatures().size(), 2);
320 assertFalse(store.getPositionalFeatures().contains(sf4));
322 assertTrue(store.delete(sf9));
323 assertEquals(store.getPositionalFeatures().size(), 1);
324 assertFalse(store.getPositionalFeatures().contains(sf9));
326 assertTrue(store.delete(sf8));
327 assertTrue(store.getPositionalFeatures().isEmpty());
330 @Test(groups = "Functional")
331 public void testAddFeature()
333 FeatureStore fs = newFeatureStore();
335 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
337 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
340 assertTrue(fs.addFeature(sf1));
341 assertEquals(fs.getFeatureCount(true), 1); // positional
342 assertEquals(fs.getFeatureCount(false), 0); // non-positional
345 * re-adding the same or an identical feature should fail
347 assertFalse(fs.addFeature(sf1));
348 assertEquals(fs.getFeatureCount(true), 1);
349 assertFalse(fs.addFeature(sf2));
350 assertEquals(fs.getFeatureCount(true), 1);
355 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
357 assertTrue(fs.addFeature(sf3));
358 assertEquals(fs.getFeatureCount(true), 1); // positional
359 assertEquals(fs.getFeatureCount(false), 1); // non-positional
360 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
362 assertFalse(fs.addFeature(sf4)); // already stored
363 assertEquals(fs.getFeatureCount(true), 1); // positional
364 assertEquals(fs.getFeatureCount(false), 1); // non-positional
369 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
371 assertTrue(fs.addFeature(sf5));
372 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
373 assertEquals(fs.getFeatureCount(false), 1); // non-positional
374 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
376 assertFalse(fs.addFeature(sf6)); // already stored
377 assertEquals(fs.getFeatureCount(true), 2); // no change
378 assertEquals(fs.getFeatureCount(false), 1); // no change
381 @Test(groups = "Functional")
382 public void testIsEmpty()
384 FeatureStore fs = newFeatureStore();
385 assertTrue(fs.isEmpty());
386 assertEquals(fs.getFeatureCount(true), 0);
391 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
394 assertFalse(fs.isEmpty());
395 assertEquals(fs.getFeatureCount(true), 1);
397 assertTrue(fs.isEmpty());
398 assertEquals(fs.getFeatureCount(true), 0);
401 * non-positional feature
403 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
405 assertFalse(fs.isEmpty());
406 assertEquals(fs.getFeatureCount(false), 1); // non-positional
407 assertEquals(fs.getFeatureCount(true), 0); // positional
409 assertTrue(fs.isEmpty());
410 assertEquals(fs.getFeatureCount(false), 0);
415 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
417 assertFalse(fs.isEmpty());
418 assertEquals(fs.getFeatureCount(true), 1);
420 assertTrue(fs.isEmpty());
421 assertEquals(fs.getFeatureCount(true), 0);
424 * sf2, sf3 added as nested features
426 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
427 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
429 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
434 assertEquals(fs.getFeatureCount(true), 3);
435 assertTrue(fs.delete(sf1));
436 assertEquals(fs.getFeatureCount(true), 2);
437 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
438 .getValue(fs, "features");
439 assertEquals(intervalStore.size(), 2);
440 assertFalse(fs.isEmpty());
441 assertTrue(fs.delete(sf2));
442 assertEquals(fs.getFeatureCount(true), 1);
443 assertFalse(fs.isEmpty());
444 assertTrue(fs.delete(sf3));
445 assertEquals(fs.getFeatureCount(true), 0);
446 assertTrue(fs.isEmpty()); // all gone
449 @Test(groups = "Functional")
450 public void testGetFeatureGroups()
452 FeatureStore fs = newFeatureStore();
453 assertTrue(fs.getFeatureGroups(true).isEmpty());
454 assertTrue(fs.getFeatureGroups(false).isEmpty());
456 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
458 Set<String> groups = fs.getFeatureGroups(true);
459 assertEquals(groups.size(), 1);
460 assertTrue(groups.contains("group1"));
463 * add another feature of the same group, delete one, delete both
465 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
467 groups = fs.getFeatureGroups(true);
468 assertEquals(groups.size(), 1);
469 assertTrue(groups.contains("group1"));
471 groups = fs.getFeatureGroups(true);
472 assertEquals(groups.size(), 1);
473 assertTrue(groups.contains("group1"));
475 groups = fs.getFeatureGroups(true);
476 assertTrue(fs.getFeatureGroups(true).isEmpty());
478 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
480 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
482 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
484 groups = fs.getFeatureGroups(true);
485 assertEquals(groups.size(), 3);
486 assertTrue(groups.contains("group2"));
487 assertTrue(groups.contains("Group2")); // case sensitive
488 assertTrue(groups.contains(null)); // null allowed
489 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
492 groups = fs.getFeatureGroups(true);
493 assertEquals(groups.size(), 2);
494 assertFalse(groups.contains("group2"));
496 groups = fs.getFeatureGroups(true);
497 assertEquals(groups.size(), 1);
498 assertFalse(groups.contains("Group2"));
500 groups = fs.getFeatureGroups(true);
501 assertTrue(groups.isEmpty());
504 * add non-positional feature
506 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
509 groups = fs.getFeatureGroups(false);
510 assertEquals(groups.size(), 1);
511 assertTrue(groups.contains("CathGroup"));
512 assertTrue(fs.delete(sf6));
513 assertTrue(fs.getFeatureGroups(false).isEmpty());
516 @Test(groups = "Functional")
517 public void testGetTotalFeatureLength()
519 FeatureStore fs = newFeatureStore();
520 assertEquals(fs.getTotalFeatureLength(), 0);
522 addFeature(fs, 10, 20); // 11
523 assertEquals(fs.getTotalFeatureLength(), 11);
524 addFeature(fs, 17, 37); // 21
525 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
526 assertEquals(fs.getTotalFeatureLength(), 93);
528 // non-positional features don't count
529 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
532 assertEquals(fs.getTotalFeatureLength(), 93);
534 // contact features count 1
535 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
536 15, 35, 1f, "group1");
538 assertEquals(fs.getTotalFeatureLength(), 94);
540 assertTrue(fs.delete(sf1));
541 assertEquals(fs.getTotalFeatureLength(), 33);
542 assertFalse(fs.delete(sf1));
543 assertEquals(fs.getTotalFeatureLength(), 33);
544 assertTrue(fs.delete(sf2));
545 assertEquals(fs.getTotalFeatureLength(), 33);
546 assertTrue(fs.delete(sf3));
547 assertEquals(fs.getTotalFeatureLength(), 32);
550 @Test(groups = "Functional")
551 public void testGetFeatureLength()
556 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
557 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
560 * non-positional feature
562 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
564 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
567 * contact feature counts 1
569 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
570 14, 28, 1f, "AGroup");
571 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
574 @Test(groups = "Functional")
575 public void testMin()
577 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
578 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
579 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
580 assertEquals(FeatureStore.min(2f, -3f), -3f);
583 @Test(groups = "Functional")
584 public void testMax()
586 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
587 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
588 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
589 assertEquals(FeatureStore.max(2f, -3f), 2f);
592 @Test(groups = "Functional")
593 public void testGetMinimumScore_getMaximumScore()
595 FeatureStore fs = newFeatureStore();
596 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
597 assertEquals(fs.getMaximumScore(true), Float.NaN);
598 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
599 assertEquals(fs.getMaximumScore(false), Float.NaN);
601 // add features with no score
602 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
605 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
608 assertEquals(fs.getMinimumScore(true), Float.NaN);
609 assertEquals(fs.getMaximumScore(true), Float.NaN);
610 assertEquals(fs.getMinimumScore(false), Float.NaN);
611 assertEquals(fs.getMaximumScore(false), Float.NaN);
613 // add positional features with score
614 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
617 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
620 assertEquals(fs.getMinimumScore(true), 1f);
621 assertEquals(fs.getMaximumScore(true), 4f);
622 assertEquals(fs.getMinimumScore(false), Float.NaN);
623 assertEquals(fs.getMaximumScore(false), Float.NaN);
625 // add non-positional features with score
626 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
629 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
632 assertEquals(fs.getMinimumScore(true), 1f);
633 assertEquals(fs.getMaximumScore(true), 4f);
634 assertEquals(fs.getMinimumScore(false), -7f);
635 assertEquals(fs.getMaximumScore(false), 11f);
637 // delete one positional and one non-positional
638 // min-max should be recomputed
639 assertTrue(fs.delete(sf6));
640 assertTrue(fs.delete(sf3));
641 assertEquals(fs.getMinimumScore(true), 4f);
642 assertEquals(fs.getMaximumScore(true), 4f);
643 assertEquals(fs.getMinimumScore(false), 11f);
644 assertEquals(fs.getMaximumScore(false), 11f);
646 // delete remaining features with score
647 assertTrue(fs.delete(sf4));
648 assertTrue(fs.delete(sf5));
649 assertEquals(fs.getMinimumScore(true), Float.NaN);
650 assertEquals(fs.getMaximumScore(true), Float.NaN);
651 assertEquals(fs.getMinimumScore(false), Float.NaN);
652 assertEquals(fs.getMaximumScore(false), Float.NaN);
654 // delete all features
655 assertTrue(fs.delete(sf1));
656 assertTrue(fs.delete(sf2));
657 assertTrue(fs.isEmpty());
658 assertEquals(fs.getMinimumScore(true), Float.NaN);
659 assertEquals(fs.getMaximumScore(true), Float.NaN);
660 assertEquals(fs.getMinimumScore(false), Float.NaN);
661 assertEquals(fs.getMaximumScore(false), Float.NaN);
664 @Test(groups = "Functional")
665 public void testListContains()
667 FeatureStore featureStore = newFeatureStore();
668 assertFalse(featureStore.listContains(null, null));
669 List<SequenceFeature> features = new ArrayList<>();
670 assertFalse(featureStore.listContains(features, null));
672 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
674 assertFalse(featureStore.listContains(null, sf1));
675 assertFalse(featureStore.listContains(features, sf1));
678 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
680 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
683 // sf2.equals(sf1) so contains should return true
684 assertTrue(featureStore.listContains(features, sf2));
685 assertFalse(featureStore.listContains(features, sf3));
688 @Test(groups = "Functional")
689 public void testGetFeaturesForGroup()
691 FeatureStore fs = newFeatureStore();
696 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
697 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
698 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
699 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
702 * sf1: positional feature in the null group
704 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
707 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
708 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
709 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
710 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
711 assertEquals(features.size(), 1);
712 assertTrue(features.contains(sf1));
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
719 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
721 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
723 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
729 features = fs.getFeaturesForGroup(true, null);
730 assertEquals(features.size(), 1);
731 assertTrue(features.contains(sf1));
733 features = fs.getFeaturesForGroup(false, null);
734 assertEquals(features.size(), 1);
735 assertTrue(features.contains(sf2));
737 features = fs.getFeaturesForGroup(true, "Uniprot");
738 assertEquals(features.size(), 1);
739 assertTrue(features.contains(sf3));
741 features = fs.getFeaturesForGroup(false, "Rfam");
742 assertEquals(features.size(), 1);
743 assertTrue(features.contains(sf4));
746 @Test(groups = "Functional")
747 public void testShiftFeatures()
749 FeatureStore fs = newFeatureStore();
750 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
752 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
755 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
758 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
761 // non-positional feature:
762 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
766 * shift all features right by 5
768 assertTrue(fs.shiftFeatures(0, 5));
770 // non-positional features untouched:
771 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
772 assertEquals(nonPos.size(), 1);
773 assertTrue(nonPos.contains(sf4));
775 // positional features are replaced
776 List<SequenceFeature> pos = fs.getPositionalFeatures();
777 assertEquals(pos.size(), 3);
778 assertFalse(pos.contains(sf1));
779 assertFalse(pos.contains(sf2));
780 assertFalse(pos.contains(sf3));
781 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
782 assertEquals(pos.get(0).getBegin(), 7);
783 assertEquals(pos.get(0).getEnd(), 10);
784 assertEquals(pos.get(1).getBegin(), 13);
785 assertEquals(pos.get(1).getEnd(), 19);
786 assertEquals(pos.get(2).getBegin(), 28);
787 assertEquals(pos.get(2).getEnd(), 37);
790 * now shift left by 15
791 * feature at [7-10] should be removed
792 * feature at [13-19] should become [1-4]
794 assertTrue(fs.shiftFeatures(0, -15));
795 pos = fs.getPositionalFeatures();
796 assertEquals(pos.size(), 2);
797 SequenceFeatures.sortFeatures(pos, true);
798 assertEquals(pos.get(0).getBegin(), 1);
799 assertEquals(pos.get(0).getEnd(), 4);
800 assertEquals(pos.get(1).getBegin(), 13);
801 assertEquals(pos.get(1).getEnd(), 22);
804 * shift right by 4 from position 2 onwards
805 * feature at [1-4] unchanged, feature at [13-22] shifts
807 assertTrue(fs.shiftFeatures(2, 4));
808 pos = fs.getPositionalFeatures();
809 assertEquals(pos.size(), 2);
810 SequenceFeatures.sortFeatures(pos, true);
811 assertEquals(pos.get(0).getBegin(), 1);
812 assertEquals(pos.get(0).getEnd(), 4);
813 assertEquals(pos.get(1).getBegin(), 17);
814 assertEquals(pos.get(1).getEnd(), 26);
817 * shift right by 4 from position 18 onwards
818 * should be no change
820 SequenceFeature f1 = pos.get(0);
821 SequenceFeature f2 = pos.get(1);
822 assertFalse(fs.shiftFeatures(18, 4)); // no update
823 pos = fs.getPositionalFeatures();
824 assertEquals(pos.size(), 2);
825 SequenceFeatures.sortFeatures(pos, true);
826 assertSame(pos.get(0), f1);
827 assertSame(pos.get(1), f2);
830 @Test(groups = "Functional")
831 public void testDelete_readd()
834 * add a feature and a nested feature
836 FeatureStore store = newFeatureStore();
837 SequenceFeature sf1 = addFeature(store, 10, 20);
838 // sf2 is nested in sf1 so will be stored in nestedFeatures
839 SequenceFeature sf2 = addFeature(store, 12, 14);
840 List<SequenceFeature> features = store.getPositionalFeatures();
841 assertEquals(features.size(), 2);
842 assertTrue(features.contains(sf1));
843 assertTrue(features.contains(sf2));
844 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
845 .getValue(store, "features");
846 assertTrue(intervalStore.contains(sf1));
847 assertTrue(intervalStore.contains(sf2));
850 * delete the first feature
852 assertTrue(store.delete(sf1));
853 features = store.getPositionalFeatures();
854 assertFalse(features.contains(sf1));
855 assertTrue(features.contains(sf2));
858 * re-add the 'nested' feature; is it now duplicated?
860 store.addFeature(sf2);
861 features = store.getPositionalFeatures();
862 assertEquals(features.size(), 1);
863 assertTrue(features.contains(sf2));
866 @Test(groups = "Functional")
867 public void testContains()
869 FeatureStore fs = newFeatureStore();
870 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
871 Float.NaN, "group1");
872 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
873 Float.NaN, "group2");
874 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
876 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
878 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
879 Float.NaN, "group1");
880 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
881 Float.NaN, "group2");
886 assertTrue(fs.contains(sf1)); // positional feature
887 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
888 assertFalse(fs.contains(sf2)); // different group
889 assertTrue(fs.contains(sf3)); // non-positional
890 assertTrue(fs.contains(new SequenceFeature(sf3)));
891 assertFalse(fs.contains(sf4)); // different score
892 assertTrue(fs.contains(sf5)); // contact feature
893 assertTrue(fs.contains(new SequenceFeature(sf5)));
894 assertFalse(fs.contains(sf6)); // different group
897 * add a nested feature
899 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
900 Float.NaN, "group1");
902 assertTrue(fs.contains(sf7));
903 assertTrue(fs.contains(new SequenceFeature(sf7)));
906 * delete the outer (enclosing, non-nested) feature
909 assertFalse(fs.contains(sf1));
910 assertTrue(fs.contains(sf7));