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;
7 import static org.testng.Assert.fail;
9 import jalview.datamodel.SequenceFeature;
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;
20 public class FeatureStoreTest
22 private FeatureStore newFeatureStore()
24 return new FeatureStore();
27 @Test(groups = "Functional")
28 public void testFindFeatures_nonNested()
30 FeatureStore fs = newFeatureStore();
31 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
33 // same range different description
34 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
35 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
36 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
38 List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
39 assertTrue(overlaps.isEmpty());
41 overlaps = fs.findFeatures(8, 10);
42 assertEquals(overlaps.size(), 2);
43 assertEquals(overlaps.get(0).getEnd(), 20);
44 assertEquals(overlaps.get(1).getEnd(), 20);
46 overlaps = fs.findFeatures(12, 16);
47 assertEquals(overlaps.size(), 3);
48 assertEquals(overlaps.get(0).getEnd(), 20);
49 assertEquals(overlaps.get(1).getEnd(), 20);
50 assertEquals(overlaps.get(2).getEnd(), 25);
52 overlaps = fs.findFeatures(33, 33);
53 assertEquals(overlaps.size(), 1);
54 assertEquals(overlaps.get(0).getEnd(), 35);
57 @Test(groups = "Functional")
58 public void testFindFeatures_nested()
60 FeatureStore fs = newFeatureStore();
61 SequenceFeature sf1 = addFeature(fs, 10, 50);
62 SequenceFeature sf2 = addFeature(fs, 10, 40);
63 SequenceFeature sf3 = addFeature(fs, 20, 30);
64 // fudge feature at same location but different group (so is added)
65 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
68 SequenceFeature sf5 = addFeature(fs, 35, 36);
70 List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
71 assertTrue(overlaps.isEmpty());
73 overlaps = fs.findFeatures(10, 15);
74 assertEquals(overlaps.size(), 2);
75 assertTrue(overlaps.contains(sf1));
76 assertTrue(overlaps.contains(sf2));
78 overlaps = fs.findFeatures(45, 60);
79 assertEquals(overlaps.size(), 1);
80 assertTrue(overlaps.contains(sf1));
82 overlaps = fs.findFeatures(32, 38);
83 assertEquals(overlaps.size(), 3);
84 assertTrue(overlaps.contains(sf1));
85 assertTrue(overlaps.contains(sf2));
86 assertTrue(overlaps.contains(sf5));
88 overlaps = fs.findFeatures(15, 25);
89 assertEquals(overlaps.size(), 4);
90 assertTrue(overlaps.contains(sf1));
91 assertTrue(overlaps.contains(sf2));
92 assertTrue(overlaps.contains(sf3));
93 assertTrue(overlaps.contains(sf4));
96 @Test(groups = "Functional")
97 public void testFindFeatures_mixed()
99 FeatureStore fs = newFeatureStore();
100 SequenceFeature sf1 = addFeature(fs, 10, 50);
101 SequenceFeature sf2 = addFeature(fs, 1, 15);
102 SequenceFeature sf3 = addFeature(fs, 20, 30);
103 SequenceFeature sf4 = addFeature(fs, 40, 100);
104 SequenceFeature sf5 = addFeature(fs, 60, 100);
105 SequenceFeature sf6 = addFeature(fs, 70, 70);
107 List<SequenceFeature> overlaps = fs.findFeatures(200, 200);
108 assertTrue(overlaps.isEmpty());
110 overlaps = fs.findFeatures(1, 9);
111 assertEquals(overlaps.size(), 1);
112 assertTrue(overlaps.contains(sf2));
114 overlaps = fs.findFeatures(5, 18);
115 assertEquals(overlaps.size(), 2);
116 assertTrue(overlaps.contains(sf1));
117 assertTrue(overlaps.contains(sf2));
119 overlaps = fs.findFeatures(30, 40);
120 assertEquals(overlaps.size(), 3);
121 assertTrue(overlaps.contains(sf1));
122 assertTrue(overlaps.contains(sf3));
123 assertTrue(overlaps.contains(sf4));
125 overlaps = fs.findFeatures(80, 90);
126 assertEquals(overlaps.size(), 2);
127 assertTrue(overlaps.contains(sf4));
128 assertTrue(overlaps.contains(sf5));
130 overlaps = fs.findFeatures(68, 70);
131 assertEquals(overlaps.size(), 3);
132 assertTrue(overlaps.contains(sf4));
133 assertTrue(overlaps.contains(sf5));
134 assertTrue(overlaps.contains(sf6));
138 * Helper method to add a feature of no particular type
145 SequenceFeature addFeature(FeatureStore fs, int from, int to)
147 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
153 @Test(groups = "Functional")
154 public void testFindFeatures_contactFeatures()
156 FeatureStore fs = newFeatureStore();
158 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
159 20, Float.NaN, null);
163 * neither contact point in range
165 List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
166 assertTrue(overlaps.isEmpty());
169 * neither contact point in range
171 overlaps = fs.findFeatures(11, 19);
172 assertTrue(overlaps.isEmpty());
175 * first contact point in range
177 overlaps = fs.findFeatures(5, 15);
178 assertEquals(overlaps.size(), 1);
179 assertTrue(overlaps.contains(sf));
182 * second contact point in range
184 overlaps = fs.findFeatures(15, 25);
185 assertEquals(overlaps.size(), 1);
186 assertTrue(overlaps.contains(sf));
189 * both contact points in range
191 overlaps = fs.findFeatures(5, 25);
192 assertEquals(overlaps.size(), 1);
193 assertTrue(overlaps.contains(sf));
196 @Test(groups = "Functional")
197 public void testGetPositionalFeatures_withResultList()
199 FeatureStore store = newFeatureStore();
200 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
202 store.addFeature(sf1);
204 SequenceFeature sf2 = new SequenceFeature("Disulphide bond", "desc", 18,
205 45, Float.NaN, null);
206 store.addFeature(sf2);
208 List<SequenceFeature> features = new ArrayList<>();
209 store.getPositionalFeatures(features);
210 assertEquals(features.size(), 2);
211 assertTrue(features.contains(sf1));
212 assertTrue(features.contains(sf2));
215 * no check for duplicates
217 features.remove(sf1);
218 assertEquals(features.size(), 1);
219 assertTrue(features.contains(sf2));
220 store.getPositionalFeatures(features);
221 assertEquals(features.size(), 3);
222 assertTrue(features.contains(sf1));
223 assertTrue(features.contains(sf2)); // two copies now
224 features.remove(sf2);
225 assertTrue(features.contains(sf2)); // one copy left
226 assertEquals(features.size(), 2);
229 * null argument throws exception
233 store.getPositionalFeatures(null);
234 fail("expected exception");
235 } catch (NullPointerException e)
241 @Test(groups = "Functional")
242 public void testGetNonPositionalFeatures()
244 FeatureStore store = newFeatureStore();
245 List<SequenceFeature> features = store.getNonPositionalFeatures();
246 assertTrue(features.isEmpty());
248 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
250 store.addFeature(sf1);
251 assertTrue(features.isEmpty());
253 SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
255 store.addFeature(sf2);
256 features = store.getNonPositionalFeatures();
257 assertEquals(features.size(), 1);
258 assertTrue(features.contains(sf2));
261 * with result list argument
264 store.getNonPositionalFeatures(features);
265 assertEquals(features.size(), 1);
266 assertTrue(features.contains(sf2));
269 * no check for duplicates
271 store.getNonPositionalFeatures(features);
272 assertEquals(features.size(), 2);
273 assertTrue(features.contains(sf2)); // two copies
274 features.remove(sf2);
275 assertTrue(features.contains(sf2));
278 * null argument throws exception
282 store.getNonPositionalFeatures(null);
283 fail("expected exception");
284 } catch (NullPointerException e)
290 @Test(groups = "Functional")
291 public void testGetPositionalFeatures()
293 FeatureStore store = newFeatureStore();
294 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
296 store.addFeature(sf1);
297 // same range, different description
298 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
300 store.addFeature(sf2);
301 // discontiguous range
302 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
304 store.addFeature(sf3);
306 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
308 store.addFeature(sf4);
310 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
312 store.addFeature(sf5);
313 // non-positional feature
314 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
316 store.addFeature(sf6);
318 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
319 18, 45, Float.NaN, null);
320 store.addFeature(sf7);
322 List<SequenceFeature> features = store.getPositionalFeatures();
323 assertEquals(features.size(), 6);
324 assertTrue(features.contains(sf1));
325 assertTrue(features.contains(sf2));
326 assertTrue(features.contains(sf3));
327 assertTrue(features.contains(sf4));
328 assertTrue(features.contains(sf5));
329 assertFalse(features.contains(sf6));
330 assertTrue(features.contains(sf7));
332 features = store.getNonPositionalFeatures();
333 assertEquals(features.size(), 1);
334 assertTrue(features.contains(sf6));
337 @Test(groups = "Functional")
338 public void testDelete()
340 FeatureStore store = newFeatureStore();
341 SequenceFeature sf1 = addFeature(store, 10, 20);
342 assertTrue(store.getPositionalFeatures().contains(sf1));
347 assertTrue(store.delete(sf1));
348 assertTrue(store.getPositionalFeatures().isEmpty());
351 * non-positional feature deletion
353 SequenceFeature sf2 = addFeature(store, 0, 0);
354 assertFalse(store.getPositionalFeatures().contains(sf2));
355 assertTrue(store.getNonPositionalFeatures().contains(sf2));
356 assertTrue(store.delete(sf2));
357 assertTrue(store.getNonPositionalFeatures().isEmpty());
360 * contact feature deletion
362 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
363 23, Float.NaN, null);
364 store.addFeature(sf3);
365 assertEquals(store.getPositionalFeatures().size(), 1);
366 assertTrue(store.getPositionalFeatures().contains(sf3));
367 assertTrue(store.delete(sf3));
368 assertTrue(store.getPositionalFeatures().isEmpty());
371 * nested feature deletion
373 SequenceFeature sf4 = addFeature(store, 20, 30);
374 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
375 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
376 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
377 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
378 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
379 assertEquals(store.getPositionalFeatures().size(), 6);
381 // delete a node with children - they take its place
382 assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5
383 assertEquals(store.getPositionalFeatures().size(), 5);
384 assertFalse(store.getPositionalFeatures().contains(sf6));
386 // delete a node with no children
387 assertTrue(store.delete(sf7));
388 assertEquals(store.getPositionalFeatures().size(), 4);
389 assertFalse(store.getPositionalFeatures().contains(sf7));
391 // delete root of NCList
392 assertTrue(store.delete(sf5));
393 assertEquals(store.getPositionalFeatures().size(), 3);
394 assertFalse(store.getPositionalFeatures().contains(sf5));
396 // continue the killing fields
397 assertTrue(store.delete(sf4));
398 assertEquals(store.getPositionalFeatures().size(), 2);
399 assertFalse(store.getPositionalFeatures().contains(sf4));
401 assertTrue(store.delete(sf9));
402 assertEquals(store.getPositionalFeatures().size(), 1);
403 assertFalse(store.getPositionalFeatures().contains(sf9));
405 assertTrue(store.delete(sf8));
406 assertTrue(store.getPositionalFeatures().isEmpty());
409 @Test(groups = "Functional")
410 public void testAddFeature()
412 FeatureStore fs = newFeatureStore();
414 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
416 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
419 assertTrue(fs.addFeature(sf1));
420 assertEquals(fs.getFeatureCount(true), 1); // positional
421 assertEquals(fs.getFeatureCount(false), 0); // non-positional
424 * re-adding the same or an identical feature should fail
426 assertFalse(fs.addFeature(sf1));
427 assertEquals(fs.getFeatureCount(true), 1);
428 assertFalse(fs.addFeature(sf2));
429 assertEquals(fs.getFeatureCount(true), 1);
434 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
436 assertTrue(fs.addFeature(sf3));
437 assertEquals(fs.getFeatureCount(true), 1); // positional
438 assertEquals(fs.getFeatureCount(false), 1); // non-positional
439 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
441 assertFalse(fs.addFeature(sf4)); // already stored
442 assertEquals(fs.getFeatureCount(true), 1); // positional
443 assertEquals(fs.getFeatureCount(false), 1); // non-positional
448 SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20,
450 assertTrue(fs.addFeature(sf5));
451 assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
452 assertEquals(fs.getFeatureCount(false), 1); // non-positional
453 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20,
455 assertFalse(fs.addFeature(sf6)); // already stored
456 assertEquals(fs.getFeatureCount(true), 2); // no change
457 assertEquals(fs.getFeatureCount(false), 1); // no change
460 @Test(groups = "Functional")
461 public void testIsEmpty()
463 FeatureStore fs = newFeatureStore();
464 assertTrue(fs.isEmpty());
465 assertEquals(fs.getFeatureCount(true), 0);
470 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
473 assertFalse(fs.isEmpty());
474 assertEquals(fs.getFeatureCount(true), 1);
476 assertTrue(fs.isEmpty());
477 assertEquals(fs.getFeatureCount(true), 0);
480 * non-positional feature
482 sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
484 assertFalse(fs.isEmpty());
485 assertEquals(fs.getFeatureCount(false), 1); // non-positional
486 assertEquals(fs.getFeatureCount(true), 0); // positional
488 assertTrue(fs.isEmpty());
489 assertEquals(fs.getFeatureCount(false), 0);
494 sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
496 assertFalse(fs.isEmpty());
497 assertEquals(fs.getFeatureCount(true), 1);
499 assertTrue(fs.isEmpty());
500 assertEquals(fs.getFeatureCount(true), 0);
503 * sf2, sf3 added as nested features
505 sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null);
506 SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40,
508 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35,
513 assertEquals(fs.getFeatureCount(true), 3);
514 assertTrue(fs.delete(sf1));
515 assertEquals(fs.getFeatureCount(true), 2);
516 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
517 .getValue(fs, "features");
518 assertEquals(intervalStore.size(), 2);
519 assertFalse(fs.isEmpty());
520 assertTrue(fs.delete(sf2));
521 assertEquals(fs.getFeatureCount(true), 1);
522 assertFalse(fs.isEmpty());
523 assertTrue(fs.delete(sf3));
524 assertEquals(fs.getFeatureCount(true), 0);
525 assertTrue(fs.isEmpty()); // all gone
528 @Test(groups = "Functional")
529 public void testGetFeatureGroups()
531 FeatureStore fs = newFeatureStore();
532 assertTrue(fs.getFeatureGroups(true).isEmpty());
533 assertTrue(fs.getFeatureGroups(false).isEmpty());
535 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
537 Set<String> groups = fs.getFeatureGroups(true);
538 assertEquals(groups.size(), 1);
539 assertTrue(groups.contains("group1"));
542 * add another feature of the same group, delete one, delete both
544 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
546 groups = fs.getFeatureGroups(true);
547 assertEquals(groups.size(), 1);
548 assertTrue(groups.contains("group1"));
550 groups = fs.getFeatureGroups(true);
551 assertEquals(groups.size(), 1);
552 assertTrue(groups.contains("group1"));
554 groups = fs.getFeatureGroups(true);
555 assertTrue(fs.getFeatureGroups(true).isEmpty());
557 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
559 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2");
561 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
563 groups = fs.getFeatureGroups(true);
564 assertEquals(groups.size(), 3);
565 assertTrue(groups.contains("group2"));
566 assertTrue(groups.contains("Group2")); // case sensitive
567 assertTrue(groups.contains(null)); // null allowed
568 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
571 groups = fs.getFeatureGroups(true);
572 assertEquals(groups.size(), 2);
573 assertFalse(groups.contains("group2"));
575 groups = fs.getFeatureGroups(true);
576 assertEquals(groups.size(), 1);
577 assertFalse(groups.contains("Group2"));
579 groups = fs.getFeatureGroups(true);
580 assertTrue(groups.isEmpty());
583 * add non-positional feature
585 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
588 groups = fs.getFeatureGroups(false);
589 assertEquals(groups.size(), 1);
590 assertTrue(groups.contains("CathGroup"));
591 assertTrue(fs.delete(sf6));
592 assertTrue(fs.getFeatureGroups(false).isEmpty());
595 @Test(groups = "Functional")
596 public void testGetTotalFeatureLength()
598 FeatureStore fs = newFeatureStore();
599 assertEquals(fs.getTotalFeatureLength(), 0);
601 addFeature(fs, 10, 20); // 11
602 assertEquals(fs.getTotalFeatureLength(), 11);
603 addFeature(fs, 17, 37); // 21
604 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
605 assertEquals(fs.getTotalFeatureLength(), 93);
607 // non-positional features don't count
608 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
611 assertEquals(fs.getTotalFeatureLength(), 93);
613 // contact features count 1
614 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc",
615 15, 35, 1f, "group1");
617 assertEquals(fs.getTotalFeatureLength(), 94);
619 assertTrue(fs.delete(sf1));
620 assertEquals(fs.getTotalFeatureLength(), 33);
621 assertFalse(fs.delete(sf1));
622 assertEquals(fs.getTotalFeatureLength(), 33);
623 assertTrue(fs.delete(sf2));
624 assertEquals(fs.getTotalFeatureLength(), 33);
625 assertTrue(fs.delete(sf3));
626 assertEquals(fs.getTotalFeatureLength(), 32);
629 @Test(groups = "Functional")
630 public void testGetFeatureLength()
635 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1");
636 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
639 * non-positional feature
641 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
643 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
646 * contact feature counts 1
648 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc",
649 14, 28, 1f, "AGroup");
650 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
653 @Test(groups = "Functional")
654 public void testMin()
656 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
657 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
658 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
659 assertEquals(FeatureStore.min(2f, -3f), -3f);
662 @Test(groups = "Functional")
663 public void testMax()
665 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
666 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
667 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
668 assertEquals(FeatureStore.max(2f, -3f), 2f);
671 @Test(groups = "Functional")
672 public void testGetMinimumScore_getMaximumScore()
674 FeatureStore fs = newFeatureStore();
675 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
676 assertEquals(fs.getMaximumScore(true), Float.NaN);
677 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
678 assertEquals(fs.getMaximumScore(false), Float.NaN);
680 // add features with no score
681 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
684 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
687 assertEquals(fs.getMinimumScore(true), Float.NaN);
688 assertEquals(fs.getMaximumScore(true), Float.NaN);
689 assertEquals(fs.getMinimumScore(false), Float.NaN);
690 assertEquals(fs.getMaximumScore(false), Float.NaN);
692 // add positional features with score
693 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
696 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
699 assertEquals(fs.getMinimumScore(true), 1f);
700 assertEquals(fs.getMaximumScore(true), 4f);
701 assertEquals(fs.getMinimumScore(false), Float.NaN);
702 assertEquals(fs.getMaximumScore(false), Float.NaN);
704 // add non-positional features with score
705 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
708 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
711 assertEquals(fs.getMinimumScore(true), 1f);
712 assertEquals(fs.getMaximumScore(true), 4f);
713 assertEquals(fs.getMinimumScore(false), -7f);
714 assertEquals(fs.getMaximumScore(false), 11f);
716 // delete one positional and one non-positional
717 // min-max should be recomputed
718 assertTrue(fs.delete(sf6));
719 assertTrue(fs.delete(sf3));
720 assertEquals(fs.getMinimumScore(true), 4f);
721 assertEquals(fs.getMaximumScore(true), 4f);
722 assertEquals(fs.getMinimumScore(false), 11f);
723 assertEquals(fs.getMaximumScore(false), 11f);
725 // delete remaining features with score
726 assertTrue(fs.delete(sf4));
727 assertTrue(fs.delete(sf5));
728 assertEquals(fs.getMinimumScore(true), Float.NaN);
729 assertEquals(fs.getMaximumScore(true), Float.NaN);
730 assertEquals(fs.getMinimumScore(false), Float.NaN);
731 assertEquals(fs.getMaximumScore(false), Float.NaN);
733 // delete all features
734 assertTrue(fs.delete(sf1));
735 assertTrue(fs.delete(sf2));
736 assertTrue(fs.isEmpty());
737 assertEquals(fs.getMinimumScore(true), Float.NaN);
738 assertEquals(fs.getMaximumScore(true), Float.NaN);
739 assertEquals(fs.getMinimumScore(false), Float.NaN);
740 assertEquals(fs.getMaximumScore(false), Float.NaN);
743 @Test(groups = "Functional")
744 public void testListContains()
746 FeatureStore featureStore = newFeatureStore();
747 assertFalse(featureStore.listContains(null, null));
748 List<SequenceFeature> features = new ArrayList<>();
749 assertFalse(featureStore.listContains(features, null));
751 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
753 assertFalse(featureStore.listContains(null, sf1));
754 assertFalse(featureStore.listContains(features, sf1));
757 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
759 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
762 // sf2.equals(sf1) so contains should return true
763 assertTrue(featureStore.listContains(features, sf2));
764 assertFalse(featureStore.listContains(features, sf3));
767 @Test(groups = "Functional")
768 public void testGetFeaturesForGroup()
770 FeatureStore fs = newFeatureStore();
775 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
776 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
777 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
778 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
781 * sf1: positional feature in the null group
783 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
786 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
787 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
788 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
789 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
790 assertEquals(features.size(), 1);
791 assertTrue(features.contains(sf1));
794 * sf2: non-positional feature in the null group
795 * sf3: positional feature in a non-null group
796 * sf4: non-positional feature in a non-null group
798 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
800 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
802 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
808 features = fs.getFeaturesForGroup(true, null);
809 assertEquals(features.size(), 1);
810 assertTrue(features.contains(sf1));
812 features = fs.getFeaturesForGroup(false, null);
813 assertEquals(features.size(), 1);
814 assertTrue(features.contains(sf2));
816 features = fs.getFeaturesForGroup(true, "Uniprot");
817 assertEquals(features.size(), 1);
818 assertTrue(features.contains(sf3));
820 features = fs.getFeaturesForGroup(false, "Rfam");
821 assertEquals(features.size(), 1);
822 assertTrue(features.contains(sf4));
825 @Test(groups = "Functional")
826 public void testShiftFeatures()
828 FeatureStore fs = newFeatureStore();
829 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
831 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
834 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
837 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
840 // non-positional feature:
841 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
845 * shift all features right by 5
847 assertTrue(fs.shiftFeatures(0, 5));
849 // non-positional features untouched:
850 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
851 assertEquals(nonPos.size(), 1);
852 assertTrue(nonPos.contains(sf4));
854 // positional features are replaced
855 List<SequenceFeature> pos = fs.getPositionalFeatures();
856 assertEquals(pos.size(), 3);
857 assertFalse(pos.contains(sf1));
858 assertFalse(pos.contains(sf2));
859 assertFalse(pos.contains(sf3));
860 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
861 assertEquals(pos.get(0).getBegin(), 7);
862 assertEquals(pos.get(0).getEnd(), 10);
863 assertEquals(pos.get(1).getBegin(), 13);
864 assertEquals(pos.get(1).getEnd(), 19);
865 assertEquals(pos.get(2).getBegin(), 28);
866 assertEquals(pos.get(2).getEnd(), 37);
869 * now shift left by 15
870 * feature at [7-10] should be removed
871 * feature at [13-19] should become [1-4]
873 assertTrue(fs.shiftFeatures(0, -15));
874 pos = fs.getPositionalFeatures();
875 assertEquals(pos.size(), 2);
876 SequenceFeatures.sortFeatures(pos, true);
877 assertEquals(pos.get(0).getBegin(), 1);
878 assertEquals(pos.get(0).getEnd(), 4);
879 assertEquals(pos.get(1).getBegin(), 13);
880 assertEquals(pos.get(1).getEnd(), 22);
883 * shift right by 4 from position 2 onwards
884 * feature at [1-4] unchanged, feature at [13-22] shifts
886 assertTrue(fs.shiftFeatures(2, 4));
887 pos = fs.getPositionalFeatures();
888 assertEquals(pos.size(), 2);
889 SequenceFeatures.sortFeatures(pos, true);
890 assertEquals(pos.get(0).getBegin(), 1);
891 assertEquals(pos.get(0).getEnd(), 4);
892 assertEquals(pos.get(1).getBegin(), 17);
893 assertEquals(pos.get(1).getEnd(), 26);
896 * shift right by 4 from position 18 onwards
897 * should be no change
899 SequenceFeature f1 = pos.get(0);
900 SequenceFeature f2 = pos.get(1);
901 assertFalse(fs.shiftFeatures(18, 4)); // no update
902 pos = fs.getPositionalFeatures();
903 assertEquals(pos.size(), 2);
904 SequenceFeatures.sortFeatures(pos, true);
905 assertSame(pos.get(0), f1);
906 assertSame(pos.get(1), f2);
909 @Test(groups = "Functional")
910 public void testDelete_readd()
913 * add a feature and a nested feature
915 FeatureStore store = newFeatureStore();
916 SequenceFeature sf1 = addFeature(store, 10, 20);
917 // sf2 is nested in sf1 so will be stored in nestedFeatures
918 SequenceFeature sf2 = addFeature(store, 12, 14);
919 List<SequenceFeature> features = store.getPositionalFeatures();
920 assertEquals(features.size(), 2);
921 assertTrue(features.contains(sf1));
922 assertTrue(features.contains(sf2));
923 Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) PA
924 .getValue(store, "features");
925 assertTrue(intervalStore.contains(sf1));
926 assertTrue(intervalStore.contains(sf2));
929 * delete the first feature
931 assertTrue(store.delete(sf1));
932 features = store.getPositionalFeatures();
933 assertFalse(features.contains(sf1));
934 assertTrue(features.contains(sf2));
937 * re-add the 'nested' feature; is it now duplicated?
939 store.addFeature(sf2);
940 features = store.getPositionalFeatures();
941 assertEquals(features.size(), 1);
942 assertTrue(features.contains(sf2));
945 @Test(groups = "Functional")
946 public void testContains()
948 FeatureStore fs = newFeatureStore();
949 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
950 Float.NaN, "group1");
951 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
952 Float.NaN, "group2");
953 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
955 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
957 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
958 Float.NaN, "group1");
959 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
960 Float.NaN, "group2");
965 assertTrue(fs.contains(sf1)); // positional feature
966 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
967 assertFalse(fs.contains(sf2)); // different group
968 assertTrue(fs.contains(sf3)); // non-positional
969 assertTrue(fs.contains(new SequenceFeature(sf3)));
970 assertFalse(fs.contains(sf4)); // different score
971 assertTrue(fs.contains(sf5)); // contact feature
972 assertTrue(fs.contains(new SequenceFeature(sf5)));
973 assertFalse(fs.contains(sf6)); // different group
976 * add a nested feature
978 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
979 Float.NaN, "group1");
981 assertTrue(fs.contains(sf7));
982 assertTrue(fs.contains(new SequenceFeature(sf7)));
985 * delete the outer (enclosing, non-nested) feature
988 assertFalse(fs.contains(sf1));
989 assertTrue(fs.contains(sf7));
992 @Test(groups = "Functional")
993 public void testFindFeatures_withResultList()
995 FeatureStore fs = newFeatureStore();
996 SequenceFeature sf1 = addFeature(fs, 10, 50);
997 SequenceFeature sf2 = addFeature(fs, 150, 250);
999 List<SequenceFeature> overlaps = new ArrayList<>();
1000 List<SequenceFeature> result = fs.findFeatures(200, 200,
1002 assertSame(result, overlaps);
1003 assertEquals(result.size(), 1);
1004 assertTrue(result.contains(sf2));
1005 assertFalse(result.contains(sf1));
1008 * if no list supplied, method creates one
1010 result = fs.findFeatures(200, 200, null);
1011 assertEquals(result.size(), 1);
1012 assertTrue(result.contains(sf2));
1013 assertFalse(result.contains(sf1));