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 'NC array' implementation of IntervalStore
23 public class FeatureStoreNCListBufferTest
25 private FeatureStore newFeatureStore()
27 return new FeatureStore(IntervalStoreType.INTERVAL_STORE_NCARRAY);
30 @Test(groups = "Functional")
31 public void testFindFeatures_nonNested()
33 FeatureStore fs = newFeatureStore();
34 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
36 // same range different description
37 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
38 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
39 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
41 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
42 assertTrue(overlaps.isEmpty());
44 overlaps = fs.findOverlappingFeatures(8, 10);
45 assertEquals(overlaps.size(), 2);
46 assertEquals(overlaps.get(0).getEnd(), 20);
47 assertEquals(overlaps.get(1).getEnd(), 20);
49 overlaps = fs.findOverlappingFeatures(12, 16);
50 assertEquals(overlaps.size(), 3);
51 assertEquals(overlaps.get(0).getEnd(), 20);
52 assertEquals(overlaps.get(1).getEnd(), 20);
53 assertEquals(overlaps.get(2).getEnd(), 25);
55 overlaps = fs.findOverlappingFeatures(33, 33);
56 assertEquals(overlaps.size(), 1);
57 assertEquals(overlaps.get(0).getEnd(), 35);
60 @Test(groups = "Functional")
61 public void testFindFeatures_nested()
63 FeatureStore fs = newFeatureStore();
64 SequenceFeature sf1 = addFeature(fs, 10, 50);
65 SequenceFeature sf2 = addFeature(fs, 10, 40);
66 SequenceFeature sf3 = addFeature(fs, 20, 30);
67 // fudge feature at same location but different group (so is added)
68 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
71 SequenceFeature sf5 = addFeature(fs, 35, 36);
73 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
74 assertTrue(overlaps.isEmpty());
76 overlaps = fs.findOverlappingFeatures(10, 15);
77 assertEquals(overlaps.size(), 2);
78 assertTrue(overlaps.contains(sf1));
79 assertTrue(overlaps.contains(sf2));
81 overlaps = fs.findOverlappingFeatures(45, 60);
82 assertEquals(overlaps.size(), 1);
83 assertTrue(overlaps.contains(sf1));
85 overlaps = fs.findOverlappingFeatures(32, 38);
86 assertEquals(overlaps.size(), 3);
87 assertTrue(overlaps.contains(sf1));
88 assertTrue(overlaps.contains(sf2));
89 assertTrue(overlaps.contains(sf5));
91 overlaps = fs.findOverlappingFeatures(15, 25);
92 assertEquals(overlaps.size(), 4);
93 assertTrue(overlaps.contains(sf1));
94 assertTrue(overlaps.contains(sf2));
95 assertTrue(overlaps.contains(sf3));
96 assertTrue(overlaps.contains(sf4));
99 @Test(groups = "Functional")
100 public void testFindFeatures_mixed()
102 FeatureStore fs = newFeatureStore();
103 SequenceFeature sf1 = addFeature(fs, 10, 50);
104 SequenceFeature sf2 = addFeature(fs, 1, 15);
105 SequenceFeature sf3 = addFeature(fs, 20, 30);
106 SequenceFeature sf4 = addFeature(fs, 40, 100);
107 SequenceFeature sf5 = addFeature(fs, 60, 100);
108 SequenceFeature sf6 = addFeature(fs, 70, 70);
110 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
111 assertTrue(overlaps.isEmpty());
113 overlaps = fs.findOverlappingFeatures(1, 9);
114 assertEquals(overlaps.size(), 1);
115 assertTrue(overlaps.contains(sf2));
117 overlaps = fs.findOverlappingFeatures(5, 18);
118 assertEquals(overlaps.size(), 2);
119 assertTrue(overlaps.contains(sf1));
120 assertTrue(overlaps.contains(sf2));
122 overlaps = fs.findOverlappingFeatures(30, 40);
123 assertEquals(overlaps.size(), 3);
124 assertTrue(overlaps.contains(sf1));
125 assertTrue(overlaps.contains(sf3));
126 assertTrue(overlaps.contains(sf4));
128 overlaps = fs.findOverlappingFeatures(80, 90);
129 assertEquals(overlaps.size(), 2);
130 assertTrue(overlaps.contains(sf4));
131 assertTrue(overlaps.contains(sf5));
133 overlaps = fs.findOverlappingFeatures(68, 70);
134 assertEquals(overlaps.size(), 3);
135 assertTrue(overlaps.contains(sf4));
136 assertTrue(overlaps.contains(sf5));
137 assertTrue(overlaps.contains(sf6));
141 * Helper method to add a feature of no particular type
148 SequenceFeature addFeature(FeatureStore fs, int from, int to)
150 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
156 @Test(groups = "Functional")
157 public void testFindFeatures_contactFeatures()
159 FeatureStore fs = newFeatureStore();
161 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
162 20, Float.NaN, null);
166 * neither contact point in range
168 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
169 assertTrue(overlaps.isEmpty());
172 * neither contact point in range
174 overlaps = fs.findOverlappingFeatures(11, 19);
175 assertTrue(overlaps.isEmpty());
178 * first contact point in range
180 overlaps = fs.findOverlappingFeatures(5, 15);
181 assertEquals(overlaps.size(), 1);
182 assertTrue(overlaps.contains(sf));
185 * second contact point in range
187 overlaps = fs.findOverlappingFeatures(15, 25);
188 assertEquals(overlaps.size(), 1);
189 assertTrue(overlaps.contains(sf));
192 * both contact points in range
194 overlaps = fs.findOverlappingFeatures(5, 25);
195 assertEquals(overlaps.size(), 1);
196 assertTrue(overlaps.contains(sf));
199 @Test(groups = "Functional")
200 public void testGetPositionalFeatures()
202 FeatureStore store = newFeatureStore();
203 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
205 store.addFeature(sf1);
206 // same range, different description
207 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
209 store.addFeature(sf2);
210 // discontiguous range
211 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
213 store.addFeature(sf3);
215 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
217 store.addFeature(sf4);
219 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
221 store.addFeature(sf5);
222 // non-positional feature
223 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
225 store.addFeature(sf6);
227 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
228 18, 45, Float.NaN, null);
229 store.addFeature(sf7);
231 List<SequenceFeature> features = store.getPositionalFeatures();
232 assertEquals(features.size(), 6);
233 assertTrue(features.contains(sf1));
234 assertTrue(features.contains(sf2));
235 assertTrue(features.contains(sf3));
236 assertTrue(features.contains(sf4));
237 assertTrue(features.contains(sf5));
238 assertFalse(features.contains(sf6));
239 assertTrue(features.contains(sf7));
241 features = store.getNonPositionalFeatures();
242 assertEquals(features.size(), 1);
243 assertTrue(features.contains(sf6));
246 @Test(groups = "Functional")
247 public void testDelete()
249 FeatureStore store = newFeatureStore();
250 SequenceFeature sf1 = addFeature(store, 10, 20);
251 assertTrue(store.getPositionalFeatures().contains(sf1));
256 assertTrue(store.delete(sf1));
257 assertTrue(store.getPositionalFeatures().isEmpty());
260 * non-positional feature deletion
262 SequenceFeature sf2 = addFeature(store, 0, 0);
263 assertFalse(store.getPositionalFeatures().contains(sf2));
264 assertTrue(store.getNonPositionalFeatures().contains(sf2));
265 assertTrue(store.delete(sf2));
266 assertTrue(store.getNonPositionalFeatures().isEmpty());
269 * contact feature deletion
271 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
272 23, Float.NaN, null);
273 store.addFeature(sf3);
274 assertEquals(store.getPositionalFeatures().size(), 1);
275 assertTrue(store.getPositionalFeatures().contains(sf3));
276 assertTrue(store.delete(sf3));
277 assertTrue(store.getPositionalFeatures().isEmpty());
280 * nested feature deletion
282 SequenceFeature sf4 = addFeature(store, 20, 30);
283 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
284 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
285 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
286 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
287 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
289 // SequenceFeature sf4 = addFeature(store, 20, 30);
290 //// SequenceFeature sf5 = addFeature(store, 22, 26);
291 ////// SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
292 //////// SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
293 //////// SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
294 ////// SequenceFeature sf7 = addFeature(store, 25, 25); // child of sf5
296 assertEquals(store.getPositionalFeatures().size(), 6);
298 // delete a node with children - they take its place
299 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
300 assertEquals(store.getPositionalFeatures().size(), 5);
301 assertFalse(store.getPositionalFeatures().contains(sf6));
303 // delete a node with no children
304 assertTrue(store.delete(sf7));
305 assertEquals(store.getPositionalFeatures().size(), 4);
306 assertFalse(store.getPositionalFeatures().contains(sf7));
308 // delete root of NCList
309 assertTrue(store.delete(sf5));
310 assertEquals(store.getPositionalFeatures().size(), 3);
311 assertFalse(store.getPositionalFeatures().contains(sf5));
313 // continue the killing fields
314 assertTrue(store.delete(sf4));
315 assertEquals(store.getPositionalFeatures().size(), 2);
316 assertFalse(store.getPositionalFeatures().contains(sf4));
318 assertTrue(store.delete(sf9));
319 assertEquals(store.getPositionalFeatures().size(), 1);
320 assertFalse(store.getPositionalFeatures().contains(sf9));
322 assertTrue(store.delete(sf8));
323 assertTrue(store.getPositionalFeatures().isEmpty());
326 @Test(groups = "Functional")
327 public void testAddFeature()
329 FeatureStore fs = newFeatureStore();
331 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
333 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
336 assertTrue(fs.addFeature(sf1));
337 assertEquals(fs.getFeatureCount(true), 1); // positional
338 assertEquals(fs.getFeatureCount(false), 0); // non-positional
341 * re-adding the same or an identical feature should fail
343 assertFalse(fs.addFeature(sf1));
344 assertEquals(fs.getFeatureCount(true), 1);
345 assertFalse(fs.addFeature(sf2));
346 assertEquals(fs.getFeatureCount(true), 1);
351 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
353 assertTrue(fs.addFeature(sf3));
354 assertEquals(fs.getFeatureCount(true), 1); // positional
355 assertEquals(fs.getFeatureCount(false), 1); // non-positional
356 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
358 assertFalse(fs.addFeature(sf4)); // already stored
359 assertEquals(fs.getFeatureCount(true), 1); // positional
360 assertEquals(fs.getFeatureCount(false), 1); // non-positional
365 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
367 assertTrue(fs.addFeature(sf5));
368 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
369 assertEquals(fs.getFeatureCount(false), 1); // non-positional
370 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
372 assertFalse(fs.addFeature(sf6)); // already stored
373 assertEquals(fs.getFeatureCount(true), 2); // no change
374 assertEquals(fs.getFeatureCount(false), 1); // no change
377 @Test(groups = "Functional")
378 public void testIsEmpty()
380 FeatureStore fs = newFeatureStore();
381 assertTrue(fs.isEmpty());
382 assertEquals(fs.getFeatureCount(true), 0);
387 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
390 assertFalse(fs.isEmpty());
391 assertEquals(fs.getFeatureCount(true), 1);
393 assertTrue(fs.isEmpty());
394 assertEquals(fs.getFeatureCount(true), 0);
397 * non-positional feature
399 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
401 assertFalse(fs.isEmpty());
402 assertEquals(fs.getFeatureCount(false), 1); // non-positional
403 assertEquals(fs.getFeatureCount(true), 0); // positional
405 assertTrue(fs.isEmpty());
406 assertEquals(fs.getFeatureCount(false), 0);
411 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
413 assertFalse(fs.isEmpty());
414 assertEquals(fs.getFeatureCount(true), 1);
416 assertTrue(fs.isEmpty());
417 assertEquals(fs.getFeatureCount(true), 0);
420 * sf2, sf3 added as nested features
422 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
423 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
425 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
430 assertEquals(fs.getFeatureCount(true), 3);
431 assertTrue(fs.delete(sf1));
432 assertEquals(fs.getFeatureCount(true), 2);
433 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
434 .getValue(fs, "features");
435 assertEquals(intervalStore.size(), 2);
436 assertFalse(fs.isEmpty());
437 assertTrue(fs.delete(sf2));
438 assertEquals(fs.getFeatureCount(true), 1);
439 assertFalse(fs.isEmpty());
440 assertTrue(fs.delete(sf3));
441 assertEquals(fs.getFeatureCount(true), 0);
442 assertTrue(fs.isEmpty()); // all gone
445 @Test(groups = "Functional")
446 public void testGetFeatureGroups()
448 FeatureStore fs = newFeatureStore();
449 assertTrue(fs.getFeatureGroups(true).isEmpty());
450 assertTrue(fs.getFeatureGroups(false).isEmpty());
452 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
454 Set<String> groups = fs.getFeatureGroups(true);
455 assertEquals(groups.size(), 1);
456 assertTrue(groups.contains("group1"));
459 * add another feature of the same group, delete one, delete both
461 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
463 groups = fs.getFeatureGroups(true);
464 assertEquals(groups.size(), 1);
465 assertTrue(groups.contains("group1"));
467 groups = fs.getFeatureGroups(true);
468 assertEquals(groups.size(), 1);
469 assertTrue(groups.contains("group1"));
471 groups = fs.getFeatureGroups(true);
472 assertTrue(fs.getFeatureGroups(true).isEmpty());
474 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
476 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
478 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
480 groups = fs.getFeatureGroups(true);
481 assertEquals(groups.size(), 3);
482 assertTrue(groups.contains("group2"));
483 assertTrue(groups.contains("Group2")); // case sensitive
484 assertTrue(groups.contains(null)); // null allowed
485 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
488 groups = fs.getFeatureGroups(true);
489 assertEquals(groups.size(), 2);
490 assertFalse(groups.contains("group2"));
492 groups = fs.getFeatureGroups(true);
493 assertEquals(groups.size(), 1);
494 assertFalse(groups.contains("Group2"));
496 groups = fs.getFeatureGroups(true);
497 assertTrue(groups.isEmpty());
500 * add non-positional feature
502 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
505 groups = fs.getFeatureGroups(false);
506 assertEquals(groups.size(), 1);
507 assertTrue(groups.contains("CathGroup"));
508 assertTrue(fs.delete(sf6));
509 assertTrue(fs.getFeatureGroups(false).isEmpty());
512 @Test(groups = "Functional")
513 public void testGetTotalFeatureLength()
515 FeatureStore fs = newFeatureStore();
516 assertEquals(fs.getTotalFeatureLength(), 0);
518 addFeature(fs, 10, 20); // 11
519 assertEquals(fs.getTotalFeatureLength(), 11);
520 addFeature(fs, 17, 37); // 21
521 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
522 assertEquals(fs.getTotalFeatureLength(), 93);
524 // non-positional features don't count
525 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
528 assertEquals(fs.getTotalFeatureLength(), 93);
530 // contact features count 1
531 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
532 15, 35, 1f, "group1");
534 assertEquals(fs.getTotalFeatureLength(), 94);
536 assertTrue(fs.delete(sf1));
537 assertEquals(fs.getTotalFeatureLength(), 33);
538 assertFalse(fs.delete(sf1));
539 assertEquals(fs.getTotalFeatureLength(), 33);
540 assertTrue(fs.delete(sf2));
541 assertEquals(fs.getTotalFeatureLength(), 33);
542 assertTrue(fs.delete(sf3));
543 assertEquals(fs.getTotalFeatureLength(), 32);
546 @Test(groups = "Functional")
547 public void testGetFeatureLength()
552 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
553 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
556 * non-positional feature
558 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
560 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
563 * contact feature counts 1
565 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
566 14, 28, 1f, "AGroup");
567 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
570 @Test(groups = "Functional")
571 public void testMin()
573 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
574 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
575 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
576 assertEquals(FeatureStore.min(2f, -3f), -3f);
579 @Test(groups = "Functional")
580 public void testMax()
582 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
583 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
584 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
585 assertEquals(FeatureStore.max(2f, -3f), 2f);
588 @Test(groups = "Functional")
589 public void testGetMinimumScore_getMaximumScore()
591 FeatureStore fs = newFeatureStore();
592 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
593 assertEquals(fs.getMaximumScore(true), Float.NaN);
594 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
595 assertEquals(fs.getMaximumScore(false), Float.NaN);
597 // add features with no score
598 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
601 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
604 assertEquals(fs.getMinimumScore(true), Float.NaN);
605 assertEquals(fs.getMaximumScore(true), Float.NaN);
606 assertEquals(fs.getMinimumScore(false), Float.NaN);
607 assertEquals(fs.getMaximumScore(false), Float.NaN);
609 // add positional features with score
610 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
613 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
616 assertEquals(fs.getMinimumScore(true), 1f);
617 assertEquals(fs.getMaximumScore(true), 4f);
618 assertEquals(fs.getMinimumScore(false), Float.NaN);
619 assertEquals(fs.getMaximumScore(false), Float.NaN);
621 // add non-positional features with score
622 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
625 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
628 assertEquals(fs.getMinimumScore(true), 1f);
629 assertEquals(fs.getMaximumScore(true), 4f);
630 assertEquals(fs.getMinimumScore(false), -7f);
631 assertEquals(fs.getMaximumScore(false), 11f);
633 // delete one positional and one non-positional
634 // min-max should be recomputed
635 assertTrue(fs.delete(sf6));
636 assertTrue(fs.delete(sf3));
637 assertEquals(fs.getMinimumScore(true), 4f);
638 assertEquals(fs.getMaximumScore(true), 4f);
639 assertEquals(fs.getMinimumScore(false), 11f);
640 assertEquals(fs.getMaximumScore(false), 11f);
642 // delete remaining features with score
643 assertTrue(fs.delete(sf4));
644 assertTrue(fs.delete(sf5));
645 assertEquals(fs.getMinimumScore(true), Float.NaN);
646 assertEquals(fs.getMaximumScore(true), Float.NaN);
647 assertEquals(fs.getMinimumScore(false), Float.NaN);
648 assertEquals(fs.getMaximumScore(false), Float.NaN);
650 // delete all features
651 assertTrue(fs.delete(sf1));
652 assertTrue(fs.delete(sf2));
653 assertTrue(fs.isEmpty());
654 assertEquals(fs.getMinimumScore(true), Float.NaN);
655 assertEquals(fs.getMaximumScore(true), Float.NaN);
656 assertEquals(fs.getMinimumScore(false), Float.NaN);
657 assertEquals(fs.getMaximumScore(false), Float.NaN);
660 @Test(groups = "Functional")
661 public void testListContains()
663 FeatureStore featureStore = newFeatureStore();
664 assertFalse(featureStore.listContains(null, null));
665 List<SequenceFeature> features = new ArrayList<>();
666 assertFalse(featureStore.listContains(features, null));
668 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
670 assertFalse(featureStore.listContains(null, sf1));
671 assertFalse(featureStore.listContains(features, sf1));
674 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
676 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
679 // sf2.equals(sf1) so contains should return true
680 assertTrue(featureStore.listContains(features, sf2));
681 assertFalse(featureStore.listContains(features, sf3));
684 @Test(groups = "Functional")
685 public void testGetFeaturesForGroup()
687 FeatureStore fs = newFeatureStore();
692 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
693 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
694 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
695 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
698 * sf1: positional feature in the null group
700 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
703 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
704 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
705 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
706 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
707 assertEquals(features.size(), 1);
708 assertTrue(features.contains(sf1));
711 * sf2: non-positional feature in the null group
712 * sf3: positional feature in a non-null group
713 * sf4: non-positional feature in a non-null group
715 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
717 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
719 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
725 features = fs.getFeaturesForGroup(true, null);
726 assertEquals(features.size(), 1);
727 assertTrue(features.contains(sf1));
729 features = fs.getFeaturesForGroup(false, null);
730 assertEquals(features.size(), 1);
731 assertTrue(features.contains(sf2));
733 features = fs.getFeaturesForGroup(true, "Uniprot");
734 assertEquals(features.size(), 1);
735 assertTrue(features.contains(sf3));
737 features = fs.getFeaturesForGroup(false, "Rfam");
738 assertEquals(features.size(), 1);
739 assertTrue(features.contains(sf4));
742 @Test(groups = "Functional")
743 public void testShiftFeatures()
745 FeatureStore fs = newFeatureStore();
746 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
748 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
751 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
754 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
757 // non-positional feature:
758 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
762 * shift all features right by 5
764 assertTrue(fs.shiftFeatures(0, 5));
766 // non-positional features untouched:
767 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
768 assertEquals(nonPos.size(), 1);
769 assertTrue(nonPos.contains(sf4));
771 // positional features are replaced
772 List<SequenceFeature> pos = fs.getPositionalFeatures();
773 assertEquals(pos.size(), 3);
774 assertFalse(pos.contains(sf1));
775 assertFalse(pos.contains(sf2));
776 assertFalse(pos.contains(sf3));
777 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
778 assertEquals(pos.get(0).getBegin(), 7);
779 assertEquals(pos.get(0).getEnd(), 10);
780 assertEquals(pos.get(1).getBegin(), 13);
781 assertEquals(pos.get(1).getEnd(), 19);
782 assertEquals(pos.get(2).getBegin(), 28);
783 assertEquals(pos.get(2).getEnd(), 37);
786 * now shift left by 15
787 * feature at [7-10] should be removed
788 * feature at [13-19] should become [1-4]
790 assertTrue(fs.shiftFeatures(0, -15));
791 pos = fs.getPositionalFeatures();
792 assertEquals(pos.size(), 2);
793 SequenceFeatures.sortFeatures(pos, true);
794 assertEquals(pos.get(0).getBegin(), 1);
795 assertEquals(pos.get(0).getEnd(), 4);
796 assertEquals(pos.get(1).getBegin(), 13);
797 assertEquals(pos.get(1).getEnd(), 22);
800 * shift right by 4 from position 2 onwards
801 * feature at [1-4] unchanged, feature at [13-22] shifts
803 assertTrue(fs.shiftFeatures(2, 4));
804 pos = fs.getPositionalFeatures();
805 assertEquals(pos.size(), 2);
806 SequenceFeatures.sortFeatures(pos, true);
807 assertEquals(pos.get(0).getBegin(), 1);
808 assertEquals(pos.get(0).getEnd(), 4);
809 assertEquals(pos.get(1).getBegin(), 17);
810 assertEquals(pos.get(1).getEnd(), 26);
813 * shift right by 4 from position 18 onwards
814 * should be no change
816 SequenceFeature f1 = pos.get(0);
817 SequenceFeature f2 = pos.get(1);
818 assertFalse(fs.shiftFeatures(18, 4)); // no update
819 pos = fs.getPositionalFeatures();
820 assertEquals(pos.size(), 2);
821 SequenceFeatures.sortFeatures(pos, true);
822 assertSame(pos.get(0), f1);
823 assertSame(pos.get(1), f2);
826 @Test(groups = "Functional")
827 public void testDelete_readd()
830 * add a feature and a nested feature
832 FeatureStore store = newFeatureStore();
833 SequenceFeature sf1 = addFeature(store, 10, 20);
834 // sf2 is nested in sf1 so will be stored in nestedFeatures
835 SequenceFeature sf2 = addFeature(store, 12, 14);
836 List<SequenceFeature> features = store.getPositionalFeatures();
837 assertEquals(features.size(), 2);
838 assertTrue(features.contains(sf1));
839 assertTrue(features.contains(sf2));
840 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
841 .getValue(store, "features");
842 assertTrue(intervalStore.contains(sf1));
843 assertTrue(intervalStore.contains(sf2));
846 * delete the first feature
848 assertTrue(store.delete(sf1));
849 features = store.getPositionalFeatures();
850 assertFalse(features.contains(sf1));
851 assertTrue(features.contains(sf2));
854 * re-add the 'nested' feature; is it now duplicated?
856 store.addFeature(sf2);
857 features = store.getPositionalFeatures();
858 assertEquals(features.size(), 1);
859 assertTrue(features.contains(sf2));
862 @Test(groups = "Functional")
863 public void testContains()
865 FeatureStore fs = newFeatureStore();
866 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
867 Float.NaN, "group1");
868 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
869 Float.NaN, "group2");
870 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
872 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
874 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
875 Float.NaN, "group1");
876 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
877 Float.NaN, "group2");
882 assertTrue(fs.contains(sf1)); // positional feature
883 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
884 assertFalse(fs.contains(sf2)); // different group
885 assertTrue(fs.contains(sf3)); // non-positional
886 assertTrue(fs.contains(new SequenceFeature(sf3)));
887 assertFalse(fs.contains(sf4)); // different score
888 assertTrue(fs.contains(sf5)); // contact feature
889 assertTrue(fs.contains(new SequenceFeature(sf5)));
890 assertFalse(fs.contains(sf6)); // different group
893 * add a nested feature
895 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
896 Float.NaN, "group1");
898 assertTrue(fs.contains(sf7));
899 assertTrue(fs.contains(new SequenceFeature(sf7)));
902 * delete the outer (enclosing, non-nested) feature
905 assertFalse(fs.contains(sf1));
906 assertTrue(fs.contains(sf7));