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.List;
15 import org.testng.annotations.Test;
18 * Tests that exercise the 'linked list' version of IntervalStore
20 public class FeatureStoreLinkedTest
22 private FeatureStore newFeatureStore()
24 return new FeatureStore(IntervalStoreType.INTERVAL_STORE_LINKED_LIST);
27 @Test(groups = "Functional")
28 public void testFindFeatures_nonNested()
30 FeatureStore fs = newFeatureStore();
31 SequenceFeature sf0 = new SequenceFeature("", "", 10, 20, Float.NaN,
34 // same range different description
35 SequenceFeature sf1 = new SequenceFeature("", "desc", 10, 20, Float.NaN, null);
37 SequenceFeature sf2 = new SequenceFeature("", "", 15, 25, Float.NaN, null);
39 SequenceFeature sf3 = new SequenceFeature("", "", 20, 35, Float.NaN, null);
42 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
43 assertTrue(overlaps.isEmpty());
45 overlaps = fs.findOverlappingFeatures(8, 10);
46 assertEquals(overlaps.size(), 2);
47 assertTrue(overlaps.contains(sf0));
48 assertTrue(overlaps.contains(sf1));
50 overlaps = fs.findOverlappingFeatures(12, 16);
51 assertEquals(overlaps.size(), 3);
52 assertTrue(overlaps.contains(sf0));
53 assertTrue(overlaps.contains(sf1));
54 assertTrue(overlaps.contains(sf2));
56 overlaps = fs.findOverlappingFeatures(33, 33);
57 assertEquals(overlaps.size(), 1);
58 assertTrue(overlaps.contains(sf3));
61 @Test(groups = "Functional")
62 public void testFindFeatures_nested()
64 FeatureStore fs = newFeatureStore();
65 SequenceFeature sf1 = addFeature(fs, 10, 50);
66 SequenceFeature sf2 = addFeature(fs, 10, 40);
67 SequenceFeature sf3 = addFeature(fs, 20, 30);
68 // fudge feature at same location but different group (so is added)
69 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
72 SequenceFeature sf5 = addFeature(fs, 35, 36);
74 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
75 assertTrue(overlaps.isEmpty());
77 overlaps = fs.findOverlappingFeatures(10, 15);
78 assertEquals(overlaps.size(), 2);
79 assertTrue(overlaps.contains(sf1));
80 assertTrue(overlaps.contains(sf2));
82 overlaps = fs.findOverlappingFeatures(45, 60);
83 assertEquals(overlaps.size(), 1);
84 assertTrue(overlaps.contains(sf1));
86 overlaps = fs.findOverlappingFeatures(32, 38);
87 assertEquals(overlaps.size(), 3);
88 assertTrue(overlaps.contains(sf1));
89 assertTrue(overlaps.contains(sf2));
90 assertTrue(overlaps.contains(sf5));
92 overlaps = fs.findOverlappingFeatures(15, 25);
93 assertEquals(overlaps.size(), 4);
94 assertTrue(overlaps.contains(sf1));
95 assertTrue(overlaps.contains(sf2));
96 assertTrue(overlaps.contains(sf3));
97 assertTrue(overlaps.contains(sf4));
100 @Test(groups = "Functional")
101 public void testFindFeatures_mixed()
103 FeatureStore fs = newFeatureStore();
104 SequenceFeature sf1 = addFeature(fs, 10, 50);
105 SequenceFeature sf2 = addFeature(fs, 1, 15);
106 SequenceFeature sf3 = addFeature(fs, 20, 30);
107 SequenceFeature sf4 = addFeature(fs, 40, 100);
108 SequenceFeature sf5 = addFeature(fs, 60, 100);
109 SequenceFeature sf6 = addFeature(fs, 70, 70);
111 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
112 assertTrue(overlaps.isEmpty());
114 overlaps = fs.findOverlappingFeatures(1, 9);
115 assertEquals(overlaps.size(), 1);
116 assertTrue(overlaps.contains(sf2));
118 overlaps = fs.findOverlappingFeatures(5, 18);
119 assertEquals(overlaps.size(), 2);
120 assertTrue(overlaps.contains(sf1));
121 assertTrue(overlaps.contains(sf2));
123 overlaps = fs.findOverlappingFeatures(30, 40);
124 assertEquals(overlaps.size(), 3);
125 assertTrue(overlaps.contains(sf1));
126 assertTrue(overlaps.contains(sf3));
127 assertTrue(overlaps.contains(sf4));
129 overlaps = fs.findOverlappingFeatures(80, 90);
130 assertEquals(overlaps.size(), 2);
131 assertTrue(overlaps.contains(sf4));
132 assertTrue(overlaps.contains(sf5));
134 overlaps = fs.findOverlappingFeatures(68, 70);
135 assertEquals(overlaps.size(), 3);
136 assertTrue(overlaps.contains(sf4));
137 assertTrue(overlaps.contains(sf5));
138 assertTrue(overlaps.contains(sf6));
142 * Helper method to add a feature of no particular type
149 SequenceFeature addFeature(FeatureStore fs, int from, int to)
151 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
157 @Test(groups = "Functional")
158 public void testFindFeatures_contactFeatures()
160 FeatureStore fs = newFeatureStore();
162 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
163 20, Float.NaN, null);
167 * neither contact point in range
169 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
170 assertTrue(overlaps.isEmpty());
173 * neither contact point in range
175 overlaps = fs.findOverlappingFeatures(11, 19);
176 assertTrue(overlaps.isEmpty());
179 * first contact point in range
181 overlaps = fs.findOverlappingFeatures(5, 15);
182 assertEquals(overlaps.size(), 1);
183 assertTrue(overlaps.contains(sf));
186 * second contact point in range
188 overlaps = fs.findOverlappingFeatures(15, 25);
189 assertEquals(overlaps.size(), 1);
190 assertTrue(overlaps.contains(sf));
193 * both contact points in range
195 overlaps = fs.findOverlappingFeatures(5, 25);
196 assertEquals(overlaps.size(), 1);
197 assertTrue(overlaps.contains(sf));
200 @Test(groups = "Functional")
201 public void testGetPositionalFeatures()
203 FeatureStore store = newFeatureStore();
204 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
206 store.addFeature(sf1);
207 // same range, different description
208 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
210 store.addFeature(sf2);
211 // discontiguous range
212 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
214 store.addFeature(sf3);
216 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
218 store.addFeature(sf4);
220 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
222 store.addFeature(sf5);
223 // non-positional feature
224 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
226 store.addFeature(sf6);
228 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
229 18, 45, Float.NaN, null);
230 store.addFeature(sf7);
232 List<SequenceFeature> features = store.getPositionalFeatures();
233 assertEquals(features.size(), 6);
234 assertTrue(features.contains(sf1));
235 assertTrue(features.contains(sf2));
236 assertTrue(features.contains(sf3));
237 assertTrue(features.contains(sf4));
238 assertTrue(features.contains(sf5));
239 assertFalse(features.contains(sf6));
240 assertTrue(features.contains(sf7));
242 features = store.getNonPositionalFeatures();
243 assertEquals(features.size(), 1);
244 assertTrue(features.contains(sf6));
247 @Test(groups = "Functional")
248 public void testDelete()
250 FeatureStore store = newFeatureStore();
251 SequenceFeature sf1 = addFeature(store, 10, 20);
252 assertTrue(store.getPositionalFeatures().contains(sf1));
257 assertTrue(store.delete(sf1));
258 assertTrue(store.getPositionalFeatures().isEmpty());
261 * non-positional feature deletion
263 SequenceFeature sf2 = addFeature(store, 0, 0);
264 assertFalse(store.getPositionalFeatures().contains(sf2));
265 assertTrue(store.getNonPositionalFeatures().contains(sf2));
266 assertTrue(store.delete(sf2));
267 assertTrue(store.getNonPositionalFeatures().isEmpty());
270 * contact feature deletion
272 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
273 23, Float.NaN, null);
274 store.addFeature(sf3);
275 assertEquals(store.getPositionalFeatures().size(), 1);
276 assertTrue(store.getPositionalFeatures().contains(sf3));
277 assertTrue(store.delete(sf3));
278 assertTrue(store.getPositionalFeatures().isEmpty());
281 * nested feature deletion
283 SequenceFeature sf4 = addFeature(store, 20, 30);
284 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
285 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
286 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
287 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
288 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
290 // SequenceFeature sf4 = addFeature(store, 20, 30);
291 //// SequenceFeature sf5 = addFeature(store, 22, 26);
292 ////// SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
293 //////// SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
294 //////// SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
295 ////// SequenceFeature sf7 = addFeature(store, 25, 25); // child of sf5
297 assertEquals(store.getPositionalFeatures().size(), 6);
299 // delete a node with children - they take its place
300 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
301 assertEquals(store.getPositionalFeatures().size(), 5);
302 assertFalse(store.getPositionalFeatures().contains(sf6));
304 // delete a node with no children
305 assertTrue(store.delete(sf7));
306 assertEquals(store.getPositionalFeatures().size(), 4);
307 assertFalse(store.getPositionalFeatures().contains(sf7));
309 // delete root of NCList
310 assertTrue(store.delete(sf5));
311 assertEquals(store.getPositionalFeatures().size(), 3);
312 assertFalse(store.getPositionalFeatures().contains(sf5));
314 // continue the killing fields
315 assertTrue(store.delete(sf4));
316 assertEquals(store.getPositionalFeatures().size(), 2);
317 assertFalse(store.getPositionalFeatures().contains(sf4));
319 assertTrue(store.delete(sf9));
320 assertEquals(store.getPositionalFeatures().size(), 1);
321 assertFalse(store.getPositionalFeatures().contains(sf9));
323 assertTrue(store.delete(sf8));
324 assertTrue(store.getPositionalFeatures().isEmpty());
327 @Test(groups = "Functional")
328 public void testAddFeature()
330 FeatureStore fs = newFeatureStore();
332 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
334 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
337 assertTrue(fs.addFeature(sf1));
338 assertEquals(fs.getFeatureCount(true), 1); // positional
339 assertEquals(fs.getFeatureCount(false), 0); // non-positional
342 * re-adding the same or an identical feature should fail
344 assertFalse(fs.addFeature(sf1));
345 assertEquals(fs.getFeatureCount(true), 1);
346 assertFalse(fs.addFeature(sf2));
347 assertEquals(fs.getFeatureCount(true), 1);
352 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
354 assertTrue(fs.addFeature(sf3));
355 assertEquals(fs.getFeatureCount(true), 1); // positional
356 assertEquals(fs.getFeatureCount(false), 1); // non-positional
357 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
359 assertFalse(fs.addFeature(sf4)); // already stored
360 assertEquals(fs.getFeatureCount(true), 1); // positional
361 assertEquals(fs.getFeatureCount(false), 1); // non-positional
366 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
368 assertTrue(fs.addFeature(sf5));
369 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
370 assertEquals(fs.getFeatureCount(false), 1); // non-positional
371 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
373 assertFalse(fs.addFeature(sf6)); // already stored
374 assertEquals(fs.getFeatureCount(true), 2); // no change
375 assertEquals(fs.getFeatureCount(false), 1); // no change
378 @Test(groups = "Functional")
379 public void testIsEmpty()
381 FeatureStore fs = newFeatureStore();
382 assertTrue(fs.isEmpty());
383 assertEquals(fs.getFeatureCount(true), 0);
388 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
391 assertFalse(fs.isEmpty());
392 assertEquals(fs.getFeatureCount(true), 1);
394 assertTrue(fs.isEmpty());
395 assertEquals(fs.getFeatureCount(true), 0);
398 * non-positional feature
400 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
402 assertFalse(fs.isEmpty());
403 assertEquals(fs.getFeatureCount(false), 1); // non-positional
404 assertEquals(fs.getFeatureCount(true), 0); // positional
406 assertTrue(fs.isEmpty());
407 assertEquals(fs.getFeatureCount(false), 0);
412 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
414 assertFalse(fs.isEmpty());
415 assertEquals(fs.getFeatureCount(true), 1);
417 assertTrue(fs.isEmpty());
418 assertEquals(fs.getFeatureCount(true), 0);
421 * sf2, sf3 added as nested features
423 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
424 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
426 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
431 assertEquals(fs.getFeatureCount(true), 3);
432 assertTrue(fs.delete(sf1));
433 assertEquals(fs.getFeatureCount(true), 2);
434 assertEquals(fs.getFeatures().size(), 2);
435 assertFalse(fs.isEmpty());
436 assertTrue(fs.delete(sf2));
437 assertEquals(fs.getFeatureCount(true), 1);
438 assertFalse(fs.isEmpty());
439 assertTrue(fs.delete(sf3));
440 assertEquals(fs.getFeatureCount(true), 0);
441 assertTrue(fs.isEmpty()); // all gone
444 @Test(groups = "Functional")
445 public void testGetFeatureGroups()
447 FeatureStore fs = newFeatureStore();
448 assertTrue(fs.getFeatureGroups(true).isEmpty());
449 assertTrue(fs.getFeatureGroups(false).isEmpty());
451 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
453 Set<String> groups = fs.getFeatureGroups(true);
454 assertEquals(groups.size(), 1);
455 assertTrue(groups.contains("group1"));
458 * add another feature of the same group, delete one, delete both
460 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
462 groups = fs.getFeatureGroups(true);
463 assertEquals(groups.size(), 1);
464 assertTrue(groups.contains("group1"));
466 groups = fs.getFeatureGroups(true);
467 assertEquals(groups.size(), 1);
468 assertTrue(groups.contains("group1"));
470 groups = fs.getFeatureGroups(true);
471 assertTrue(fs.getFeatureGroups(true).isEmpty());
473 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
475 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
477 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
479 groups = fs.getFeatureGroups(true);
480 assertEquals(groups.size(), 3);
481 assertTrue(groups.contains("group2"));
482 assertTrue(groups.contains("Group2")); // case sensitive
483 assertTrue(groups.contains(null)); // null allowed
484 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
487 groups = fs.getFeatureGroups(true);
488 assertEquals(groups.size(), 2);
489 assertFalse(groups.contains("group2"));
491 groups = fs.getFeatureGroups(true);
492 assertEquals(groups.size(), 1);
493 assertFalse(groups.contains("Group2"));
495 groups = fs.getFeatureGroups(true);
496 assertTrue(groups.isEmpty());
499 * add non-positional feature
501 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
504 groups = fs.getFeatureGroups(false);
505 assertEquals(groups.size(), 1);
506 assertTrue(groups.contains("CathGroup"));
507 assertTrue(fs.delete(sf6));
508 assertTrue(fs.getFeatureGroups(false).isEmpty());
511 @Test(groups = "Functional")
512 public void testGetTotalFeatureLength()
514 FeatureStore fs = newFeatureStore();
515 assertEquals(fs.getTotalFeatureLength(), 0);
517 addFeature(fs, 10, 20); // 11
518 assertEquals(fs.getTotalFeatureLength(), 11);
519 addFeature(fs, 17, 37); // 21
520 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
521 assertEquals(fs.getTotalFeatureLength(), 93);
523 // non-positional features don't count
524 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
527 assertEquals(fs.getTotalFeatureLength(), 93);
529 // contact features count 1
530 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
531 15, 35, 1f, "group1");
533 assertEquals(fs.getTotalFeatureLength(), 94);
535 assertTrue(fs.delete(sf1));
536 assertEquals(fs.getTotalFeatureLength(), 33);
537 assertFalse(fs.delete(sf1));
538 assertEquals(fs.getTotalFeatureLength(), 33);
539 assertTrue(fs.delete(sf2));
540 assertEquals(fs.getTotalFeatureLength(), 33);
541 assertTrue(fs.delete(sf3));
542 assertEquals(fs.getTotalFeatureLength(), 32);
545 @Test(groups = "Functional")
546 public void testGetFeatureLength()
551 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
552 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
555 * non-positional feature
557 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
559 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
562 * contact feature counts 1
564 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
565 14, 28, 1f, "AGroup");
566 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
569 @Test(groups = "Functional")
570 public void testMin()
572 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
573 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
574 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
575 assertEquals(FeatureStore.min(2f, -3f), -3f);
578 @Test(groups = "Functional")
579 public void testMax()
581 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
582 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
583 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
584 assertEquals(FeatureStore.max(2f, -3f), 2f);
587 @Test(groups = "Functional")
588 public void testGetMinimumScore_getMaximumScore()
590 FeatureStore fs = newFeatureStore();
591 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
592 assertEquals(fs.getMaximumScore(true), Float.NaN);
593 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
594 assertEquals(fs.getMaximumScore(false), Float.NaN);
596 // add features with no score
597 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
600 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
603 assertEquals(fs.getMinimumScore(true), Float.NaN);
604 assertEquals(fs.getMaximumScore(true), Float.NaN);
605 assertEquals(fs.getMinimumScore(false), Float.NaN);
606 assertEquals(fs.getMaximumScore(false), Float.NaN);
608 // add positional features with score
609 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
612 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
615 assertEquals(fs.getMinimumScore(true), 1f);
616 assertEquals(fs.getMaximumScore(true), 4f);
617 assertEquals(fs.getMinimumScore(false), Float.NaN);
618 assertEquals(fs.getMaximumScore(false), Float.NaN);
620 // add non-positional features with score
621 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
624 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
627 assertEquals(fs.getMinimumScore(true), 1f);
628 assertEquals(fs.getMaximumScore(true), 4f);
629 assertEquals(fs.getMinimumScore(false), -7f);
630 assertEquals(fs.getMaximumScore(false), 11f);
632 // delete one positional and one non-positional
633 // min-max should be recomputed
634 assertTrue(fs.delete(sf6));
635 assertTrue(fs.delete(sf3));
636 assertEquals(fs.getMinimumScore(true), 4f);
637 assertEquals(fs.getMaximumScore(true), 4f);
638 assertEquals(fs.getMinimumScore(false), 11f);
639 assertEquals(fs.getMaximumScore(false), 11f);
641 // delete remaining features with score
642 assertTrue(fs.delete(sf4));
643 assertTrue(fs.delete(sf5));
644 assertEquals(fs.getMinimumScore(true), Float.NaN);
645 assertEquals(fs.getMaximumScore(true), Float.NaN);
646 assertEquals(fs.getMinimumScore(false), Float.NaN);
647 assertEquals(fs.getMaximumScore(false), Float.NaN);
649 // delete all features
650 assertTrue(fs.delete(sf1));
651 assertTrue(fs.delete(sf2));
652 assertTrue(fs.isEmpty());
653 assertEquals(fs.getMinimumScore(true), Float.NaN);
654 assertEquals(fs.getMaximumScore(true), Float.NaN);
655 assertEquals(fs.getMinimumScore(false), Float.NaN);
656 assertEquals(fs.getMaximumScore(false), Float.NaN);
659 @Test(groups = "Functional")
660 public void testListContains()
662 FeatureStore featureStore = newFeatureStore();
663 assertFalse(featureStore.listContains(null, null));
664 List<SequenceFeature> features = new ArrayList<>();
665 assertFalse(featureStore.listContains(features, null));
667 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
669 assertFalse(featureStore.listContains(null, sf1));
670 assertFalse(featureStore.listContains(features, sf1));
673 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
675 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
678 // sf2.equals(sf1) so contains should return true
679 assertTrue(featureStore.listContains(features, sf2));
680 assertFalse(featureStore.listContains(features, sf3));
683 @Test(groups = "Functional")
684 public void testGetFeaturesForGroup()
686 FeatureStore fs = newFeatureStore();
691 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
692 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
693 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
694 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
697 * sf1: positional feature in the null group
699 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
702 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
703 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
704 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
705 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
706 assertEquals(features.size(), 1);
707 assertTrue(features.contains(sf1));
710 * sf2: non-positional feature in the null group
711 * sf3: positional feature in a non-null group
712 * sf4: non-positional feature in a non-null group
714 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
716 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
718 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
724 features = fs.getFeaturesForGroup(true, null);
725 assertEquals(features.size(), 1);
726 assertTrue(features.contains(sf1));
728 features = fs.getFeaturesForGroup(false, null);
729 assertEquals(features.size(), 1);
730 assertTrue(features.contains(sf2));
732 features = fs.getFeaturesForGroup(true, "Uniprot");
733 assertEquals(features.size(), 1);
734 assertTrue(features.contains(sf3));
736 features = fs.getFeaturesForGroup(false, "Rfam");
737 assertEquals(features.size(), 1);
738 assertTrue(features.contains(sf4));
741 @Test(groups = "Functional")
742 public void testShiftFeatures()
744 FeatureStore fs = newFeatureStore();
745 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
747 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
750 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
753 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
756 // non-positional feature:
757 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
761 * shift all features right by 5
763 assertTrue(fs.shiftFeatures(0, 5));
765 // non-positional features untouched:
766 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
767 assertEquals(nonPos.size(), 1);
768 assertTrue(nonPos.contains(sf4));
770 // positional features are replaced
771 List<SequenceFeature> pos = fs.getPositionalFeatures();
772 assertEquals(pos.size(), 3);
773 assertFalse(pos.contains(sf1));
774 assertFalse(pos.contains(sf2));
775 assertFalse(pos.contains(sf3));
776 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
777 assertEquals(pos.get(0).getBegin(), 7);
778 assertEquals(pos.get(0).getEnd(), 10);
779 assertEquals(pos.get(1).getBegin(), 13);
780 assertEquals(pos.get(1).getEnd(), 19);
781 assertEquals(pos.get(2).getBegin(), 28);
782 assertEquals(pos.get(2).getEnd(), 37);
785 * now shift left by 15
786 * feature at [7-10] should be removed
787 * feature at [13-19] should become [1-4]
789 assertTrue(fs.shiftFeatures(0, -15));
790 pos = fs.getPositionalFeatures();
791 assertEquals(pos.size(), 2);
792 SequenceFeatures.sortFeatures(pos, true);
793 assertEquals(pos.get(0).getBegin(), 1);
794 assertEquals(pos.get(0).getEnd(), 4);
795 assertEquals(pos.get(1).getBegin(), 13);
796 assertEquals(pos.get(1).getEnd(), 22);
799 * shift right by 4 from position 2 onwards
800 * feature at [1-4] unchanged, feature at [13-22] shifts
802 assertTrue(fs.shiftFeatures(2, 4));
803 pos = fs.getPositionalFeatures();
804 assertEquals(pos.size(), 2);
805 SequenceFeatures.sortFeatures(pos, true);
806 assertEquals(pos.get(0).getBegin(), 1);
807 assertEquals(pos.get(0).getEnd(), 4);
808 assertEquals(pos.get(1).getBegin(), 17);
809 assertEquals(pos.get(1).getEnd(), 26);
812 * shift right by 4 from position 18 onwards
813 * should be no change
815 SequenceFeature f1 = pos.get(0);
816 SequenceFeature f2 = pos.get(1);
817 assertFalse(fs.shiftFeatures(18, 4)); // no update
818 pos = fs.getPositionalFeatures();
819 assertEquals(pos.size(), 2);
820 SequenceFeatures.sortFeatures(pos, true);
821 assertSame(pos.get(0), f1);
822 assertSame(pos.get(1), f2);
825 @Test(groups = "Functional")
826 public void testDelete_readd()
829 * add a feature and a nested feature
831 FeatureStore store = newFeatureStore();
832 SequenceFeature sf1 = addFeature(store, 10, 20);
833 // sf2 is nested in sf1 so will be stored in nestedFeatures
834 SequenceFeature sf2 = addFeature(store, 12, 14);
835 List<SequenceFeature> features = store.getPositionalFeatures();
836 assertEquals(features.size(), 2);
837 assertTrue(features.contains(sf1));
838 assertTrue(features.contains(sf2));
839 assertTrue(store.getFeatures().contains(sf1));
840 assertTrue(store.getFeatures().contains(sf2));
843 * delete the first feature
845 assertTrue(store.delete(sf1));
846 features = store.getPositionalFeatures();
847 assertFalse(features.contains(sf1));
848 assertTrue(features.contains(sf2));
851 * re-add the 'nested' feature; is it now duplicated?
853 store.addFeature(sf2);
854 features = store.getPositionalFeatures();
855 assertEquals(features.size(), 1);
856 assertTrue(features.contains(sf2));
859 @Test(groups = "Functional")
860 public void testContains()
862 FeatureStore fs = newFeatureStore();
863 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
864 Float.NaN, "group1");
865 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
866 Float.NaN, "group2");
867 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
869 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
871 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
872 Float.NaN, "group1");
873 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
874 Float.NaN, "group2");
879 assertTrue(fs.contains(sf1)); // positional feature
880 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
881 assertFalse(fs.contains(sf2)); // different group
882 assertTrue(fs.contains(sf3)); // non-positional
883 assertTrue(fs.contains(new SequenceFeature(sf3)));
884 assertFalse(fs.contains(sf4)); // different score
885 assertTrue(fs.contains(sf5)); // contact feature
886 assertTrue(fs.contains(new SequenceFeature(sf5)));
887 assertFalse(fs.contains(sf6)); // different group
890 * add a nested feature
892 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
893 Float.NaN, "group1");
895 assertTrue(fs.contains(sf7));
896 assertTrue(fs.contains(new SequenceFeature(sf7)));
899 * delete the outer (enclosing, non-nested) feature
902 assertFalse(fs.contains(sf1));
903 assertTrue(fs.contains(sf7));