2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.datamodel.features;
23 import static org.testng.Assert.assertEquals;
24 import static org.testng.Assert.assertFalse;
25 import static org.testng.Assert.assertSame;
26 import static org.testng.Assert.assertTrue;
28 import jalview.datamodel.SequenceFeature;
30 import java.util.ArrayList;
31 import java.util.List;
34 import org.testng.annotations.Test;
36 public class FeatureStoreTest
39 @Test(groups = "Functional")
40 public void testFindFeatures_nonNested()
42 FeatureStore fs = new FeatureStore();
43 fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN, null));
44 // same range different description
45 fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null));
46 fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
47 fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
49 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
50 assertTrue(overlaps.isEmpty());
52 overlaps = fs.findOverlappingFeatures(8, 10);
53 assertEquals(overlaps.size(), 2);
54 assertEquals(overlaps.get(0).getEnd(), 20);
55 assertEquals(overlaps.get(1).getEnd(), 20);
57 overlaps = fs.findOverlappingFeatures(12, 16);
58 assertEquals(overlaps.size(), 3);
59 assertEquals(overlaps.get(0).getEnd(), 20);
60 assertEquals(overlaps.get(1).getEnd(), 20);
61 assertEquals(overlaps.get(2).getEnd(), 25);
63 overlaps = fs.findOverlappingFeatures(33, 33);
64 assertEquals(overlaps.size(), 1);
65 assertEquals(overlaps.get(0).getEnd(), 35);
68 @Test(groups = "Functional")
69 public void testFindFeatures_nested()
71 FeatureStore fs = new FeatureStore();
72 SequenceFeature sf1 = addFeature(fs, 10, 50);
73 SequenceFeature sf2 = addFeature(fs, 10, 40);
74 SequenceFeature sf3 = addFeature(fs, 20, 30);
75 // fudge feature at same location but different group (so is added)
76 SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN,
79 SequenceFeature sf5 = addFeature(fs, 35, 36);
81 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
82 assertTrue(overlaps.isEmpty());
84 overlaps = fs.findOverlappingFeatures(10, 15);
85 assertEquals(overlaps.size(), 2);
86 assertTrue(overlaps.contains(sf1));
87 assertTrue(overlaps.contains(sf2));
89 overlaps = fs.findOverlappingFeatures(45, 60);
90 assertEquals(overlaps.size(), 1);
91 assertTrue(overlaps.contains(sf1));
93 overlaps = fs.findOverlappingFeatures(32, 38);
94 assertEquals(overlaps.size(), 3);
95 assertTrue(overlaps.contains(sf1));
96 assertTrue(overlaps.contains(sf2));
97 assertTrue(overlaps.contains(sf5));
99 overlaps = fs.findOverlappingFeatures(15, 25);
100 assertEquals(overlaps.size(), 4);
101 assertTrue(overlaps.contains(sf1));
102 assertTrue(overlaps.contains(sf2));
103 assertTrue(overlaps.contains(sf3));
104 assertTrue(overlaps.contains(sf4));
107 @Test(groups = "Functional")
108 public void testFindFeatures_mixed()
110 FeatureStore fs = new FeatureStore();
111 SequenceFeature sf1 = addFeature(fs, 10, 50);
112 SequenceFeature sf2 = addFeature(fs, 1, 15);
113 SequenceFeature sf3 = addFeature(fs, 20, 30);
114 SequenceFeature sf4 = addFeature(fs, 40, 100);
115 SequenceFeature sf5 = addFeature(fs, 60, 100);
116 SequenceFeature sf6 = addFeature(fs, 70, 70);
118 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
119 assertTrue(overlaps.isEmpty());
121 overlaps = fs.findOverlappingFeatures(1, 9);
122 assertEquals(overlaps.size(), 1);
123 assertTrue(overlaps.contains(sf2));
125 overlaps = fs.findOverlappingFeatures(5, 18);
126 assertEquals(overlaps.size(), 2);
127 assertTrue(overlaps.contains(sf1));
128 assertTrue(overlaps.contains(sf2));
130 overlaps = fs.findOverlappingFeatures(30, 40);
131 assertEquals(overlaps.size(), 3);
132 assertTrue(overlaps.contains(sf1));
133 assertTrue(overlaps.contains(sf3));
134 assertTrue(overlaps.contains(sf4));
136 overlaps = fs.findOverlappingFeatures(80, 90);
137 assertEquals(overlaps.size(), 2);
138 assertTrue(overlaps.contains(sf4));
139 assertTrue(overlaps.contains(sf5));
141 overlaps = fs.findOverlappingFeatures(68, 70);
142 assertEquals(overlaps.size(), 3);
143 assertTrue(overlaps.contains(sf4));
144 assertTrue(overlaps.contains(sf5));
145 assertTrue(overlaps.contains(sf6));
149 * Helper method to add a feature of no particular type
156 SequenceFeature addFeature(FeatureStore fs, int from, int to)
158 SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN,
164 @Test(groups = "Functional")
165 public void testFindFeatures_contactFeatures()
167 FeatureStore fs = new FeatureStore();
169 SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
170 20, Float.NaN, null);
174 * neither contact point in range
176 List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
177 assertTrue(overlaps.isEmpty());
180 * neither contact point in range
182 overlaps = fs.findOverlappingFeatures(11, 19);
183 assertTrue(overlaps.isEmpty());
186 * first contact point in range
188 overlaps = fs.findOverlappingFeatures(5, 15);
189 assertEquals(overlaps.size(), 1);
190 assertTrue(overlaps.contains(sf));
193 * second contact point in range
195 overlaps = fs.findOverlappingFeatures(15, 25);
196 assertEquals(overlaps.size(), 1);
197 assertTrue(overlaps.contains(sf));
200 * both contact points in range
202 overlaps = fs.findOverlappingFeatures(5, 25);
203 assertEquals(overlaps.size(), 1);
204 assertTrue(overlaps.contains(sf));
207 @Test(groups = "Functional")
208 public void testGetPositionalFeatures()
210 FeatureStore store = new FeatureStore();
211 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
213 store.addFeature(sf1);
214 // same range, different description
215 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
217 store.addFeature(sf2);
218 // discontiguous range
219 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
221 store.addFeature(sf3);
223 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
225 store.addFeature(sf4);
227 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
229 store.addFeature(sf5);
230 // non-positional feature
231 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
233 store.addFeature(sf6);
235 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc", 18,
236 45, Float.NaN, null);
237 store.addFeature(sf7);
239 List<SequenceFeature> features = store.getPositionalFeatures();
240 assertEquals(features.size(), 6);
241 assertTrue(features.contains(sf1));
242 assertTrue(features.contains(sf2));
243 assertTrue(features.contains(sf3));
244 assertTrue(features.contains(sf4));
245 assertTrue(features.contains(sf5));
246 assertFalse(features.contains(sf6));
247 assertTrue(features.contains(sf7));
249 features = store.getNonPositionalFeatures();
250 assertEquals(features.size(), 1);
251 assertTrue(features.contains(sf6));
254 @Test(groups = "Functional")
255 public void testDelete()
257 FeatureStore store = new FeatureStore();
258 SequenceFeature sf1 = addFeature(store, 10, 20);
259 assertTrue(store.getPositionalFeatures().contains(sf1));
264 assertTrue(store.delete(sf1));
265 assertTrue(store.getPositionalFeatures().isEmpty());
268 * non-positional feature deletion
270 SequenceFeature sf2 = addFeature(store, 0, 0);
271 assertFalse(store.getPositionalFeatures().contains(sf2));
272 assertTrue(store.getNonPositionalFeatures().contains(sf2));
273 assertTrue(store.delete(sf2));
274 assertTrue(store.getNonPositionalFeatures().isEmpty());
277 * contact feature deletion
279 SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11, 23,
281 store.addFeature(sf3);
282 assertEquals(store.getPositionalFeatures().size(), 1);
283 assertTrue(store.getPositionalFeatures().contains(sf3));
284 assertTrue(store.delete(sf3));
285 assertTrue(store.getPositionalFeatures().isEmpty());
288 * nested feature deletion
290 SequenceFeature sf4 = addFeature(store, 20, 30);
291 SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList
292 SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5
293 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6
294 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6
295 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6
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 = new FeatureStore();
331 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
333 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
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 = new FeatureStore();
381 assertTrue(fs.isEmpty());
382 assertEquals(fs.getFeatureCount(true), 0);
387 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
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,
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, Float.NaN,
426 SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35, Float.NaN,
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,
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,
464 groups = fs.getFeatureGroups(true);
465 assertEquals(groups.size(), 1);
466 assertTrue(groups.contains("group1"));
468 groups = fs.getFeatureGroups(true);
469 assertEquals(groups.size(), 1);
470 assertTrue(groups.contains("group1"));
472 groups = fs.getFeatureGroups(true);
473 assertTrue(fs.getFeatureGroups(true).isEmpty());
475 SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f,
478 SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f,
481 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f,
484 groups = fs.getFeatureGroups(true);
485 assertEquals(groups.size(), 3);
486 assertTrue(groups.contains("group2"));
487 assertTrue(groups.contains("Group2")); // case sensitive
488 assertTrue(groups.contains(null)); // null allowed
489 assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional
492 groups = fs.getFeatureGroups(true);
493 assertEquals(groups.size(), 2);
494 assertFalse(groups.contains("group2"));
496 groups = fs.getFeatureGroups(true);
497 assertEquals(groups.size(), 1);
498 assertFalse(groups.contains("Group2"));
500 groups = fs.getFeatureGroups(true);
501 assertTrue(groups.isEmpty());
504 * add non-positional feature
506 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
509 groups = fs.getFeatureGroups(false);
510 assertEquals(groups.size(), 1);
511 assertTrue(groups.contains("CathGroup"));
512 assertTrue(fs.delete(sf6));
513 assertTrue(fs.getFeatureGroups(false).isEmpty());
516 @Test(groups = "Functional")
517 public void testGetTotalFeatureLength()
519 FeatureStore fs = new FeatureStore();
520 assertEquals(fs.getTotalFeatureLength(), 0);
522 addFeature(fs, 10, 20); // 11
523 assertEquals(fs.getTotalFeatureLength(), 11);
524 addFeature(fs, 17, 37); // 21
525 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61
526 assertEquals(fs.getTotalFeatureLength(), 93);
528 // non-positional features don't count
529 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
532 assertEquals(fs.getTotalFeatureLength(), 93);
534 // contact features count 1
535 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc", 15,
538 assertEquals(fs.getTotalFeatureLength(), 94);
540 assertTrue(fs.delete(sf1));
541 assertEquals(fs.getTotalFeatureLength(), 33);
542 assertFalse(fs.delete(sf1));
543 assertEquals(fs.getTotalFeatureLength(), 33);
544 assertTrue(fs.delete(sf2));
545 assertEquals(fs.getTotalFeatureLength(), 33);
546 assertTrue(fs.delete(sf3));
547 assertEquals(fs.getTotalFeatureLength(), 32);
550 @Test(groups = "Functional")
551 public void testGetFeatureLength()
556 SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f,
558 assertEquals(FeatureStore.getFeatureLength(sf1), 11);
561 * non-positional feature
563 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
565 assertEquals(FeatureStore.getFeatureLength(sf2), 0);
568 * contact feature counts 1
570 SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc", 14,
572 assertEquals(FeatureStore.getFeatureLength(sf3), 1);
575 @Test(groups = "Functional")
576 public void testMin()
578 assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN);
579 assertEquals(FeatureStore.min(Float.NaN, 2f), 2f);
580 assertEquals(FeatureStore.min(-2f, Float.NaN), -2f);
581 assertEquals(FeatureStore.min(2f, -3f), -3f);
584 @Test(groups = "Functional")
585 public void testMax()
587 assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN);
588 assertEquals(FeatureStore.max(Float.NaN, 2f), 2f);
589 assertEquals(FeatureStore.max(-2f, Float.NaN), -2f);
590 assertEquals(FeatureStore.max(2f, -3f), 2f);
593 @Test(groups = "Functional")
594 public void testGetMinimumScore_getMaximumScore()
596 FeatureStore fs = new FeatureStore();
597 assertEquals(fs.getMinimumScore(true), Float.NaN); // positional
598 assertEquals(fs.getMaximumScore(true), Float.NaN);
599 assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional
600 assertEquals(fs.getMaximumScore(false), Float.NaN);
602 // add features with no score
603 SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0,
606 SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20,
609 assertEquals(fs.getMinimumScore(true), Float.NaN);
610 assertEquals(fs.getMaximumScore(true), Float.NaN);
611 assertEquals(fs.getMinimumScore(false), Float.NaN);
612 assertEquals(fs.getMaximumScore(false), Float.NaN);
614 // add positional features with score
615 SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f,
618 SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f,
621 assertEquals(fs.getMinimumScore(true), 1f);
622 assertEquals(fs.getMaximumScore(true), 4f);
623 assertEquals(fs.getMinimumScore(false), Float.NaN);
624 assertEquals(fs.getMaximumScore(false), Float.NaN);
626 // add non-positional features with score
627 SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f,
630 SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f,
633 assertEquals(fs.getMinimumScore(true), 1f);
634 assertEquals(fs.getMaximumScore(true), 4f);
635 assertEquals(fs.getMinimumScore(false), -7f);
636 assertEquals(fs.getMaximumScore(false), 11f);
638 // delete one positional and one non-positional
639 // min-max should be recomputed
640 assertTrue(fs.delete(sf6));
641 assertTrue(fs.delete(sf3));
642 assertEquals(fs.getMinimumScore(true), 4f);
643 assertEquals(fs.getMaximumScore(true), 4f);
644 assertEquals(fs.getMinimumScore(false), 11f);
645 assertEquals(fs.getMaximumScore(false), 11f);
647 // delete remaining features with score
648 assertTrue(fs.delete(sf4));
649 assertTrue(fs.delete(sf5));
650 assertEquals(fs.getMinimumScore(true), Float.NaN);
651 assertEquals(fs.getMaximumScore(true), Float.NaN);
652 assertEquals(fs.getMinimumScore(false), Float.NaN);
653 assertEquals(fs.getMaximumScore(false), Float.NaN);
655 // delete all features
656 assertTrue(fs.delete(sf1));
657 assertTrue(fs.delete(sf2));
658 assertTrue(fs.isEmpty());
659 assertEquals(fs.getMinimumScore(true), Float.NaN);
660 assertEquals(fs.getMaximumScore(true), Float.NaN);
661 assertEquals(fs.getMinimumScore(false), Float.NaN);
662 assertEquals(fs.getMaximumScore(false), Float.NaN);
665 @Test(groups = "Functional")
666 public void testListContains()
668 assertFalse(FeatureStore.listContains(null, null));
669 List<SequenceFeature> features = new ArrayList<>();
670 assertFalse(FeatureStore.listContains(features, null));
672 SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
674 assertFalse(FeatureStore.listContains(null, sf1));
675 assertFalse(FeatureStore.listContains(features, sf1));
678 SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f,
680 SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f,
683 // sf2.equals(sf1) so contains should return true
684 assertTrue(FeatureStore.listContains(features, sf2));
685 assertFalse(FeatureStore.listContains(features, sf3));
688 @Test(groups = "Functional")
689 public void testGetFeaturesForGroup()
691 FeatureStore fs = new FeatureStore();
696 assertTrue(fs.getFeaturesForGroup(true, null).isEmpty());
697 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
698 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
699 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
702 * sf1: positional feature in the null group
704 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
707 assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty());
708 assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty());
709 assertTrue(fs.getFeaturesForGroup(false, null).isEmpty());
710 List<SequenceFeature> features = fs.getFeaturesForGroup(true, null);
711 assertEquals(features.size(), 1);
712 assertTrue(features.contains(sf1));
715 * sf2: non-positional feature in the null group
716 * sf3: positional feature in a non-null group
717 * sf4: non-positional feature in a non-null group
719 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
721 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
723 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
729 features = fs.getFeaturesForGroup(true, null);
730 assertEquals(features.size(), 1);
731 assertTrue(features.contains(sf1));
733 features = fs.getFeaturesForGroup(false, null);
734 assertEquals(features.size(), 1);
735 assertTrue(features.contains(sf2));
737 features = fs.getFeaturesForGroup(true, "Uniprot");
738 assertEquals(features.size(), 1);
739 assertTrue(features.contains(sf3));
741 features = fs.getFeaturesForGroup(false, "Rfam");
742 assertEquals(features.size(), 1);
743 assertTrue(features.contains(sf4));
746 @Test(groups = "Functional")
747 public void testShiftFeatures()
749 FeatureStore fs = new FeatureStore();
750 assertFalse(fs.shiftFeatures(0, 1)); // nothing to do
752 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
755 SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null);
758 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
761 // non-positional feature:
762 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null);
766 * shift all features right by 5
768 assertTrue(fs.shiftFeatures(0, 5));
770 // non-positional features untouched:
771 List<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
772 assertEquals(nonPos.size(), 1);
773 assertTrue(nonPos.contains(sf4));
775 // positional features are replaced
776 List<SequenceFeature> pos = fs.getPositionalFeatures();
777 assertEquals(pos.size(), 3);
778 assertFalse(pos.contains(sf1));
779 assertFalse(pos.contains(sf2));
780 assertFalse(pos.contains(sf3));
781 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
782 assertEquals(pos.get(0).getBegin(), 7);
783 assertEquals(pos.get(0).getEnd(), 10);
784 assertEquals(pos.get(1).getBegin(), 13);
785 assertEquals(pos.get(1).getEnd(), 19);
786 assertEquals(pos.get(2).getBegin(), 28);
787 assertEquals(pos.get(2).getEnd(), 37);
790 * now shift left by 15
791 * feature at [7-10] should be removed
792 * feature at [13-19] should become [1-4]
794 assertTrue(fs.shiftFeatures(0, -15));
795 pos = fs.getPositionalFeatures();
796 assertEquals(pos.size(), 2);
797 SequenceFeatures.sortFeatures(pos, true);
798 assertEquals(pos.get(0).getBegin(), 1);
799 assertEquals(pos.get(0).getEnd(), 4);
800 assertEquals(pos.get(1).getBegin(), 13);
801 assertEquals(pos.get(1).getEnd(), 22);
804 * shift right by 4 from position 2 onwards
805 * feature at [1-4] unchanged, feature at [13-22] shifts
807 assertTrue(fs.shiftFeatures(2, 4));
808 pos = fs.getPositionalFeatures();
809 assertEquals(pos.size(), 2);
810 SequenceFeatures.sortFeatures(pos, true);
811 assertEquals(pos.get(0).getBegin(), 1);
812 assertEquals(pos.get(0).getEnd(), 4);
813 assertEquals(pos.get(1).getBegin(), 17);
814 assertEquals(pos.get(1).getEnd(), 26);
817 * shift right by 4 from position 18 onwards
818 * should be no change
820 SequenceFeature f1 = pos.get(0);
821 SequenceFeature f2 = pos.get(1);
822 assertFalse(fs.shiftFeatures(18, 4)); // no update
823 pos = fs.getPositionalFeatures();
824 assertEquals(pos.size(), 2);
825 SequenceFeatures.sortFeatures(pos, true);
826 assertSame(pos.get(0), f1);
827 assertSame(pos.get(1), f2);
830 @Test(groups = "Functional")
831 public void testDelete_readd()
834 * add a feature and a nested feature
836 FeatureStore store = new FeatureStore();
837 SequenceFeature sf1 = addFeature(store, 10, 20);
838 // sf2 is nested in sf1 so will be stored in nestedFeatures
839 SequenceFeature sf2 = addFeature(store, 12, 14);
840 List<SequenceFeature> features = store.getPositionalFeatures();
841 assertEquals(features.size(), 2);
842 assertTrue(features.contains(sf1));
843 assertTrue(features.contains(sf2));
844 assertTrue(store.features.contains(sf1));
845 assertTrue(store.features.contains(sf2));
848 * delete the first feature
850 assertTrue(store.delete(sf1));
851 features = store.getPositionalFeatures();
852 assertFalse(features.contains(sf1));
853 assertTrue(features.contains(sf2));
856 * re-add the 'nested' feature; is it now duplicated?
858 store.addFeature(sf2);
859 features = store.getPositionalFeatures();
860 assertEquals(features.size(), 1);
861 assertTrue(features.contains(sf2));
864 @Test(groups = "Functional")
865 public void testContains()
867 FeatureStore fs = new FeatureStore();
868 SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
870 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20, Float.NaN,
872 SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
874 SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
876 SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
877 Float.NaN, "group1");
878 SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
879 Float.NaN, "group2");
884 assertTrue(fs.contains(sf1)); // positional feature
885 assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
886 assertFalse(fs.contains(sf2)); // different group
887 assertTrue(fs.contains(sf3)); // non-positional
888 assertTrue(fs.contains(new SequenceFeature(sf3)));
889 assertFalse(fs.contains(sf4)); // different score
890 assertTrue(fs.contains(sf5)); // contact feature
891 assertTrue(fs.contains(new SequenceFeature(sf5)));
892 assertFalse(fs.contains(sf6)); // different group
895 * add a nested feature
897 SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16, Float.NaN,
900 assertTrue(fs.contains(sf7));
901 assertTrue(fs.contains(new SequenceFeature(sf7)));
904 * delete the outer (enclosing, non-nested) feature
907 assertFalse(fs.contains(sf1));
908 assertTrue(fs.contains(sf7));