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 java.util.ArrayList;
12 import org.testng.annotations.Test;
14 import jalview.datamodel.SequenceFeature;
16 public class FeatureStoreTest
19 @Test(groups = "Functional")
20 public void testFindFeatures_nonNested()
22 FeatureStore fs = new FeatureStore();
23 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
25 // same range different description
26 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
27 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
28 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
30 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
31 assertTrue(overlaps.isEmpty());
33 overlaps = fs.findOverlappingFeatures(8, 10);
34 assertEquals(overlaps.size(), 2);
35 assertEquals(overlaps.get(0).getEnd(), 20);
36 assertEquals(overlaps.get(1).getEnd(), 20);
38 overlaps = fs.findOverlappingFeatures(12, 16);
39 assertEquals(overlaps.size(), 3);
40 assertEquals(overlaps.get(0).getEnd(), 20);
41 assertEquals(overlaps.get(1).getEnd(), 20);
42 assertEquals(overlaps.get(2).getEnd(), 25);
44 overlaps = fs.findOverlappingFeatures(33, 33);
45 assertEquals(overlaps.size(), 1);
46 assertEquals(overlaps.get(0).getEnd(), 35);
49 @Test(groups = "Functional")
50 public void testFindFeatures_nested()
52 FeatureStore fs = new FeatureStore();
53 SequenceFeature sf1 = addFeature(fs, 10, 50);
54 SequenceFeature sf2 = addFeature(fs, 10, 40);
55 SequenceFeature sf3 = addFeature(fs, 20, 30);
56 // fudge feature at same location but different group (so is added)
57 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
60 SequenceFeature sf5 = addFeature(fs, 35, 36);
62 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
63 assertTrue(overlaps.isEmpty());
65 overlaps = fs.findOverlappingFeatures(10, 15);
66 assertEquals(overlaps.size(), 2);
67 assertTrue(overlaps.contains(sf1));
68 assertTrue(overlaps.contains(sf2));
70 overlaps = fs.findOverlappingFeatures(45, 60);
71 assertEquals(overlaps.size(), 1);
72 assertTrue(overlaps.contains(sf1));
74 overlaps = fs.findOverlappingFeatures(32, 38);
75 assertEquals(overlaps.size(), 3);
76 assertTrue(overlaps.contains(sf1));
77 assertTrue(overlaps.contains(sf2));
78 assertTrue(overlaps.contains(sf5));
80 overlaps = fs.findOverlappingFeatures(15, 25);
81 assertEquals(overlaps.size(), 4);
82 assertTrue(overlaps.contains(sf1));
83 assertTrue(overlaps.contains(sf2));
84 assertTrue(overlaps.contains(sf3));
85 assertTrue(overlaps.contains(sf4));
88 @Test(groups = "Functional")
89 public void testFindFeatures_colocated()
91 FeatureStore fs = new FeatureStore();
92 SequenceFeature sf1 = new SequenceFeature("domain", "Cath", 10, 50, Float.NaN,
95 SequenceFeature sf2 = new SequenceFeature("domain", "Pfam", 10, 50, Float.NaN,
98 List<SequenceFeature> features = fs.findOverlappingFeatures(1, 100);
101 * check co-located features are returned in the order they were added
103 assertEquals(features.size(), 2);
104 assertSame(features.get(0), sf1);
105 assertSame(features.get(1), sf2);
108 @Test(groups = "Functional")
109 public void testFindFeatures_mixed()
111 FeatureStore fs = new FeatureStore();
112 SequenceFeature sf1 = addFeature(fs, 10, 50);
113 SequenceFeature sf2 = addFeature(fs, 1, 15);
114 SequenceFeature sf3 = addFeature(fs, 20, 30);
115 SequenceFeature sf4 = addFeature(fs, 40, 100);
116 SequenceFeature sf5 = addFeature(fs, 60, 100);
117 SequenceFeature sf6 = addFeature(fs, 70, 70);
119 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
120 assertTrue(overlaps.isEmpty());
122 overlaps = fs.findOverlappingFeatures(1, 9);
123 assertEquals(overlaps.size(), 1);
124 assertTrue(overlaps.contains(sf2));
126 overlaps = fs.findOverlappingFeatures(5, 18);
127 assertEquals(overlaps.size(), 2);
128 assertTrue(overlaps.contains(sf1));
129 assertTrue(overlaps.contains(sf2));
131 overlaps = fs.findOverlappingFeatures(30, 40);
132 assertEquals(overlaps.size(), 3);
133 assertTrue(overlaps.contains(sf1));
134 assertTrue(overlaps.contains(sf3));
135 assertTrue(overlaps.contains(sf4));
137 overlaps = fs.findOverlappingFeatures(80, 90);
138 assertEquals(overlaps.size(), 2);
139 assertTrue(overlaps.contains(sf4));
140 assertTrue(overlaps.contains(sf5));
142 overlaps = fs.findOverlappingFeatures(68, 70);
143 assertEquals(overlaps.size(), 3);
144 assertTrue(overlaps.contains(sf4));
145 assertTrue(overlaps.contains(sf5));
146 assertTrue(overlaps.contains(sf6));
150 * Helper method to add a feature of no particular type
157 SequenceFeature addFeature(FeatureStore fs, int from, int to)
159 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
165 @Test(groups = "Functional")
166 public void testFindFeatures_contactFeatures()
168 FeatureStore fs = new FeatureStore();
170 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
171 20, Float.NaN, null);
175 * neither contact point in range
177 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
178 assertTrue(overlaps.isEmpty());
181 * neither contact point in range
183 overlaps = fs.findOverlappingFeatures(11, 19);
184 assertTrue(overlaps.isEmpty());
187 * first contact point in range
189 overlaps = fs.findOverlappingFeatures(5, 15);
190 assertEquals(overlaps.size(), 1);
191 assertTrue(overlaps.contains(sf));
194 * second contact point in range
196 overlaps = fs.findOverlappingFeatures(15, 25);
197 assertEquals(overlaps.size(), 1);
198 assertTrue(overlaps.contains(sf));
201 * both contact points in range
203 overlaps = fs.findOverlappingFeatures(5, 25);
204 assertEquals(overlaps.size(), 1);
205 assertTrue(overlaps.contains(sf));
208 @Test(groups = "Functional")
209 public void testGetPositionalFeatures()
211 FeatureStore store = new FeatureStore();
212 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
214 store.addFeature(sf1);
215 // same range, different description
216 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
218 store.addFeature(sf2);
219 // discontiguous range
220 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
222 store.addFeature(sf3);
224 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
226 store.addFeature(sf4);
228 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
230 store.addFeature(sf5);
231 // non-positional feature
232 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
234 store.addFeature(sf6);
236 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
237 18, 45, Float.NaN, null);
238 store.addFeature(sf7);
240 List<SequenceFeature> features = store.getPositionalFeatures();
241 assertEquals(features.size(), 6);
242 assertTrue(features.contains(sf1));
243 assertTrue(features.contains(sf2));
244 assertTrue(features.contains(sf3));
245 assertTrue(features.contains(sf4));
246 assertTrue(features.contains(sf5));
247 assertFalse(features.contains(sf6));
248 assertTrue(features.contains(sf7));
250 features = store.getNonPositionalFeatures();
251 assertEquals(features.size(), 1);
252 assertTrue(features.contains(sf6));
255 @Test(groups = "Functional")
256 public void testDelete()
258 FeatureStore store = new FeatureStore();
259 SequenceFeature sf1 = addFeature(store, 10, 20);
260 assertTrue(store.getPositionalFeatures().contains(sf1));
265 assertTrue(store.delete(sf1));
266 assertTrue(store.getPositionalFeatures().isEmpty());
269 * non-positional feature deletion
271 SequenceFeature sf2 = addFeature(store, 0, 0);
272 assertFalse(store.getPositionalFeatures().contains(sf2));
273 assertTrue(store.getNonPositionalFeatures().contains(sf2));
274 assertTrue(store.delete(sf2));
275 assertTrue(store.getNonPositionalFeatures().isEmpty());
278 * contact feature deletion
280 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
281 23, Float.NaN, null);
282 store.addFeature(sf3);
283 assertEquals(store.getPositionalFeatures().size(), 1);
284 assertTrue(store.getPositionalFeatures().contains(sf3));
285 assertTrue(store.delete(sf3));
286 assertTrue(store.getPositionalFeatures().isEmpty());
289 * nested feature deletion
291 SequenceFeature sf4 = addFeature(store, 20, 30);
292 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
293 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
294 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
295 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
296 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
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 = new FeatureStore();
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 = new FeatureStore();
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.features.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 = new FeatureStore();
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 = new FeatureStore();
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 = new FeatureStore();
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 assertFalse(FeatureStore.listContains(null, null));
663 List<SequenceFeature> features = new ArrayList<>();
664 assertFalse(FeatureStore.listContains(features, null));
666 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
668 assertFalse(FeatureStore.listContains(null, sf1));
669 assertFalse(FeatureStore.listContains(features, sf1));
672 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
674 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
677 // sf2.equals(sf1) so contains should return true
678 assertTrue(FeatureStore.listContains(features, sf2));
679 assertFalse(FeatureStore.listContains(features, sf3));
682 @Test(groups = "Functional")
683 public void testGetFeaturesForGroup()
685 FeatureStore fs = new FeatureStore();
690 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
691 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
692 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
693 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
696 * sf1: positional feature in the null group
698 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
701 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
702 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
703 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
704 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
705 assertEquals(features.size(), 1);
706 assertTrue(features.contains(sf1));
709 * sf2: non-positional feature in the null group
710 * sf3: positional feature in a non-null group
711 * sf4: non-positional feature in a non-null group
713 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
715 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
717 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
723 features = fs.getFeaturesForGroup(true, null);
724 assertEquals(features.size(), 1);
725 assertTrue(features.contains(sf1));
727 features = fs.getFeaturesForGroup(false, null);
728 assertEquals(features.size(), 1);
729 assertTrue(features.contains(sf2));
731 features = fs.getFeaturesForGroup(true, "Uniprot");
732 assertEquals(features.size(), 1);
733 assertTrue(features.contains(sf3));
735 features = fs.getFeaturesForGroup(false, "Rfam");
736 assertEquals(features.size(), 1);
737 assertTrue(features.contains(sf4));
740 @Test(groups = "Functional")
741 public void testShiftFeatures()
743 FeatureStore fs = new FeatureStore();
744 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
746 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
749 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
752 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
755 // non-positional feature:
756 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
760 * shift all features right by 5
762 assertTrue(fs.shiftFeatures(0, 5));
764 // non-positional features untouched:
765 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
766 assertEquals(nonPos.size(), 1);
767 assertTrue(nonPos.contains(sf4));
769 // positional features are replaced
770 List<SequenceFeature> pos = fs.getPositionalFeatures();
771 assertEquals(pos.size(), 3);
772 assertFalse(pos.contains(sf1));
773 assertFalse(pos.contains(sf2));
774 assertFalse(pos.contains(sf3));
775 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
776 assertEquals(pos.get(0).getBegin(), 7);
777 assertEquals(pos.get(0).getEnd(), 10);
778 assertEquals(pos.get(1).getBegin(), 13);
779 assertEquals(pos.get(1).getEnd(), 19);
780 assertEquals(pos.get(2).getBegin(), 28);
781 assertEquals(pos.get(2).getEnd(), 37);
784 * now shift left by 15
785 * feature at [7-10] should be removed
786 * feature at [13-19] should become [1-4]
788 assertTrue(fs.shiftFeatures(0, -15));
789 pos = fs.getPositionalFeatures();
790 assertEquals(pos.size(), 2);
791 SequenceFeatures.sortFeatures(pos, true);
792 assertEquals(pos.get(0).getBegin(), 1);
793 assertEquals(pos.get(0).getEnd(), 4);
794 assertEquals(pos.get(1).getBegin(), 13);
795 assertEquals(pos.get(1).getEnd(), 22);
798 * shift right by 4 from position 2 onwards
799 * feature at [1-4] unchanged, feature at [13-22] shifts
801 assertTrue(fs.shiftFeatures(2, 4));
802 pos = fs.getPositionalFeatures();
803 assertEquals(pos.size(), 2);
804 SequenceFeatures.sortFeatures(pos, true);
805 assertEquals(pos.get(0).getBegin(), 1);
806 assertEquals(pos.get(0).getEnd(), 4);
807 assertEquals(pos.get(1).getBegin(), 17);
808 assertEquals(pos.get(1).getEnd(), 26);
811 * shift right by 4 from position 18 onwards
812 * should be no change
814 SequenceFeature f1 = pos.get(0);
815 SequenceFeature f2 = pos.get(1);
816 assertFalse(fs.shiftFeatures(18, 4)); // no update
817 pos = fs.getPositionalFeatures();
818 assertEquals(pos.size(), 2);
819 SequenceFeatures.sortFeatures(pos, true);
820 assertSame(pos.get(0), f1);
821 assertSame(pos.get(1), f2);
824 @Test(groups = "Functional")
825 public void testDelete_readd()
828 * add a feature and a nested feature
830 FeatureStore store = new FeatureStore();
831 SequenceFeature sf1 = addFeature(store, 10, 20);
832 // sf2 is nested in sf1 so will be stored in nestedFeatures
833 SequenceFeature sf2 = addFeature(store, 12, 14);
834 List<SequenceFeature> features = store.getPositionalFeatures();
835 assertEquals(features.size(), 2);
836 assertTrue(features.contains(sf1));
837 assertTrue(features.contains(sf2));
838 assertTrue(store.features.contains(sf1));
839 assertTrue(store.features.contains(sf2));
842 * delete the first feature
844 assertTrue(store.delete(sf1));
845 features = store.getPositionalFeatures();
846 assertFalse(features.contains(sf1));
847 assertTrue(features.contains(sf2));
850 * re-add the 'nested' feature; is it now duplicated?
852 store.addFeature(sf2);
853 features = store.getPositionalFeatures();
854 assertEquals(features.size(), 1);
855 assertTrue(features.contains(sf2));
858 @Test(groups = "Functional")
859 public void testContains()
861 FeatureStore fs = new FeatureStore();
862 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
863 Float.NaN, "group1");
864 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
865 Float.NaN, "group2");
866 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
868 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
870 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
871 Float.NaN, "group1");
872 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
873 Float.NaN, "group2");
878 assertTrue(fs.contains(sf1)); // positional feature
879 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
880 assertFalse(fs.contains(sf2)); // different group
881 assertTrue(fs.contains(sf3)); // non-positional
882 assertTrue(fs.contains(new SequenceFeature(sf3)));
883 assertFalse(fs.contains(sf4)); // different score
884 assertTrue(fs.contains(sf5)); // contact feature
885 assertTrue(fs.contains(new SequenceFeature(sf5)));
886 assertFalse(fs.contains(sf6)); // different group
889 * add a nested feature
891 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
892 Float.NaN, "group1");
894 assertTrue(fs.contains(sf7));
895 assertTrue(fs.contains(new SequenceFeature(sf7)));
898 * delete the outer (enclosing, non-nested) feature
901 assertFalse(fs.contains(sf1));
902 assertTrue(fs.contains(sf7));