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;
10 import java.util.ArrayList;
11 import java.util.Iterator;
12 import java.util.List;
16 import junit.extensions.PA;
18 import org.testng.annotations.Test;
20 public class SequenceFeaturesTest
22 @Test(groups = "Functional")
23 public void testConstructor()
25 SequenceFeaturesI store = new SequenceFeatures();
26 assertFalse(store.hasFeatures());
28 store = new SequenceFeatures((List<SequenceFeature>) null);
29 assertFalse(store.hasFeatures());
31 List<SequenceFeature> features = new ArrayList<>();
32 store = new SequenceFeatures(features);
33 assertFalse(store.hasFeatures());
35 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
38 SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 15, 18,
40 features.add(sf2); // nested
41 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc2", 0, 0,
42 Float.NaN, null); // non-positional
44 store = new SequenceFeatures(features);
45 assertTrue(store.hasFeatures());
46 assertEquals(2, store.getFeatureCount(true)); // positional
47 assertEquals(1, store.getFeatureCount(false)); // non-positional
48 assertFalse(store.add(sf1)); // already contained
49 assertFalse(store.add(sf2)); // already contained
50 assertFalse(store.add(sf3)); // already contained
53 @Test(groups = "Functional")
54 public void testGetPositionalFeatures()
56 SequenceFeaturesI store = new SequenceFeatures();
57 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
60 // same range, different description
61 SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
64 // discontiguous range
65 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
69 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
73 SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
76 // non-positional feature
77 SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
81 SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
82 18, 45, Float.NaN, null);
84 // different feature type
85 SequenceFeature sf8 = new SequenceFeature("Pfam", "desc", 30, 40,
88 SequenceFeature sf9 = new SequenceFeature("Pfam", "desc", 15, 35,
93 * get all positional features
95 List<SequenceFeature> features = store.getPositionalFeatures();
96 assertEquals(features.size(), 8);
97 assertTrue(features.contains(sf1));
98 assertTrue(features.contains(sf2));
99 assertTrue(features.contains(sf3));
100 assertTrue(features.contains(sf4));
101 assertTrue(features.contains(sf5));
102 assertFalse(features.contains(sf6)); // non-positional
103 assertTrue(features.contains(sf7));
104 assertTrue(features.contains(sf8));
105 assertTrue(features.contains(sf9));
108 * get features by type
110 assertTrue(store.getPositionalFeatures((String) null).isEmpty());
111 assertTrue(store.getPositionalFeatures("Cath").isEmpty());
112 assertTrue(store.getPositionalFeatures("METAL").isEmpty());
114 features = store.getPositionalFeatures("Metal");
115 assertEquals(features.size(), 5);
116 assertTrue(features.contains(sf1));
117 assertTrue(features.contains(sf2));
118 assertTrue(features.contains(sf3));
119 assertTrue(features.contains(sf4));
120 assertTrue(features.contains(sf5));
121 assertFalse(features.contains(sf6));
123 features = store.getPositionalFeatures("Disulphide bond");
124 assertEquals(features.size(), 1);
125 assertTrue(features.contains(sf7));
127 features = store.getPositionalFeatures("Pfam");
128 assertEquals(features.size(), 2);
129 assertTrue(features.contains(sf8));
130 assertTrue(features.contains(sf9));
133 @Test(groups = "Functional")
134 public void testGetContactFeatures()
136 SequenceFeaturesI store = new SequenceFeatures();
138 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
142 SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
146 SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
147 18, 45, Float.NaN, null);
149 // repeat for different feature type
150 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
153 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
156 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
157 45, Float.NaN, null);
161 * get all contact features
163 List<SequenceFeature> features = store.getContactFeatures();
164 assertEquals(features.size(), 2);
165 assertTrue(features.contains(sf3));
166 assertTrue(features.contains(sf6));
169 * get contact features by type
171 assertTrue(store.getContactFeatures((String) null).isEmpty());
172 assertTrue(store.getContactFeatures("Cath").isEmpty());
173 assertTrue(store.getContactFeatures("Pfam").isEmpty());
174 assertTrue(store.getContactFeatures("DISULPHIDE BOND").isEmpty());
176 features = store.getContactFeatures("Disulphide bond");
177 assertEquals(features.size(), 1);
178 assertTrue(features.contains(sf3));
180 features = store.getContactFeatures("Disulfide bond");
181 assertEquals(features.size(), 1);
182 assertTrue(features.contains(sf6));
185 @Test(groups = "Functional")
186 public void testGetNonPositionalFeatures()
188 SequenceFeaturesI store = new SequenceFeatures();
190 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
194 SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
198 SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
199 18, 45, Float.NaN, null);
201 // repeat for different feature type
202 SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
205 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
208 SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
209 45, Float.NaN, null);
211 // one more non-positional, different description
212 SequenceFeature sf7 = new SequenceFeature("Pfam", "desc2", 0, 0,
217 * get all non-positional features
219 List<SequenceFeature> features = store.getNonPositionalFeatures();
220 assertEquals(features.size(), 3);
221 assertTrue(features.contains(sf2));
222 assertTrue(features.contains(sf5));
223 assertTrue(features.contains(sf7));
226 * get non-positional features by type
228 assertTrue(store.getNonPositionalFeatures((String) null).isEmpty());
229 assertTrue(store.getNonPositionalFeatures("Cath").isEmpty());
230 assertTrue(store.getNonPositionalFeatures("PFAM").isEmpty());
232 features = store.getNonPositionalFeatures("Metal");
233 assertEquals(features.size(), 1);
234 assertTrue(features.contains(sf2));
236 features = store.getNonPositionalFeatures("Pfam");
237 assertEquals(features.size(), 2);
238 assertTrue(features.contains(sf5));
239 assertTrue(features.contains(sf7));
243 * Helper method to add a feature of no particular type
251 SequenceFeature addFeature(SequenceFeaturesI sf, String type, int from,
254 SequenceFeature sf1 = new SequenceFeature(type, "", from, to,
261 @Test(groups = "Functional")
262 public void testFindFeatures()
264 SequenceFeaturesI sf = new SequenceFeatures();
265 SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
266 SequenceFeature sf2 = addFeature(sf, "Pfam", 1, 15);
267 SequenceFeature sf3 = addFeature(sf, "Pfam", 20, 30);
268 SequenceFeature sf4 = addFeature(sf, "Pfam", 40, 100);
269 SequenceFeature sf5 = addFeature(sf, "Pfam", 60, 100);
270 SequenceFeature sf6 = addFeature(sf, "Pfam", 70, 70);
271 SequenceFeature sf7 = addFeature(sf, "Cath", 10, 50);
272 SequenceFeature sf8 = addFeature(sf, "Cath", 1, 15);
273 SequenceFeature sf9 = addFeature(sf, "Cath", 20, 30);
274 SequenceFeature sf10 = addFeature(sf, "Cath", 40, 100);
275 SequenceFeature sf11 = addFeature(sf, "Cath", 60, 100);
276 SequenceFeature sf12 = addFeature(sf, "Cath", 70, 70);
278 List<SequenceFeature> overlaps = sf.findFeatures(200, 200, "Pfam");
279 assertTrue(overlaps.isEmpty());
281 overlaps = sf.findFeatures( 1, 9, "Pfam");
282 assertEquals(overlaps.size(), 1);
283 assertTrue(overlaps.contains(sf2));
285 overlaps = sf.findFeatures( 5, 18, "Pfam");
286 assertEquals(overlaps.size(), 2);
287 assertTrue(overlaps.contains(sf1));
288 assertTrue(overlaps.contains(sf2));
290 overlaps = sf.findFeatures(30, 40, "Pfam");
291 assertEquals(overlaps.size(), 3);
292 assertTrue(overlaps.contains(sf1));
293 assertTrue(overlaps.contains(sf3));
294 assertTrue(overlaps.contains(sf4));
296 overlaps = sf.findFeatures( 80, 90, "Pfam");
297 assertEquals(overlaps.size(), 2);
298 assertTrue(overlaps.contains(sf4));
299 assertTrue(overlaps.contains(sf5));
301 overlaps = sf.findFeatures( 68, 70, "Pfam");
302 assertEquals(overlaps.size(), 3);
303 assertTrue(overlaps.contains(sf4));
304 assertTrue(overlaps.contains(sf5));
305 assertTrue(overlaps.contains(sf6));
307 overlaps = sf.findFeatures(16, 69, "Cath");
308 assertEquals(overlaps.size(), 4);
309 assertTrue(overlaps.contains(sf7));
310 assertFalse(overlaps.contains(sf8));
311 assertTrue(overlaps.contains(sf9));
312 assertTrue(overlaps.contains(sf10));
313 assertTrue(overlaps.contains(sf11));
314 assertFalse(overlaps.contains(sf12));
316 assertTrue(sf.findFeatures(0, 1000, "Metal").isEmpty());
318 overlaps = sf.findFeatures(7, 7, (String) null);
319 assertTrue(overlaps.isEmpty());
322 @Test(groups = "Functional")
323 public void testDelete()
325 SequenceFeaturesI sf = new SequenceFeatures();
326 SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
327 assertTrue(sf.getPositionalFeatures().contains(sf1));
329 assertFalse(sf.delete(null));
330 SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 15, 0f, null);
331 assertFalse(sf.delete(sf2)); // not added, can't delete it
332 assertTrue(sf.delete(sf1));
333 assertTrue(sf.getPositionalFeatures().isEmpty());
336 @Test(groups = "Functional")
337 public void testHasFeatures()
339 SequenceFeaturesI sf = new SequenceFeatures();
340 assertFalse(sf.hasFeatures());
342 SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
343 assertTrue(sf.hasFeatures());
346 assertFalse(sf.hasFeatures());
350 * Tests for the method that gets feature groups for positional or
351 * non-positional features
353 @Test(groups = "Functional")
354 public void testGetFeatureGroups()
356 SequenceFeaturesI sf = new SequenceFeatures();
357 assertTrue(sf.getFeatureGroups(true).isEmpty());
358 assertTrue(sf.getFeatureGroups(false).isEmpty());
361 * add a non-positional feature (begin/end = 0/0)
363 SequenceFeature sfx = new SequenceFeature("AType", "Desc", 0, 0, 0f,
366 Set<String> groups = sf.getFeatureGroups(true); // for positional
367 assertTrue(groups.isEmpty());
368 groups = sf.getFeatureGroups(false); // for non-positional
369 assertEquals(groups.size(), 1);
370 assertTrue(groups.contains("AGroup"));
371 groups = sf.getFeatureGroups(false, "AType");
372 assertEquals(groups.size(), 1);
373 assertTrue(groups.contains("AGroup"));
374 groups = sf.getFeatureGroups(true, "AnotherType");
375 assertTrue(groups.isEmpty());
378 * add, then delete, more non-positional features of different types
380 SequenceFeature sfy = new SequenceFeature("AnotherType", "Desc", 0, 0,
384 SequenceFeature sfz = new SequenceFeature("AThirdType", "Desc", 0, 0,
388 groups = sf.getFeatureGroups(false);
389 assertEquals(groups.size(), 3);
390 assertTrue(groups.contains("AGroup"));
391 assertTrue(groups.contains("AnotherGroup"));
392 assertTrue(groups.contains(null)); // null is a possible group
395 groups = sf.getFeatureGroups(false);
396 assertEquals(groups.size(), 1);
397 assertTrue(groups.contains("AGroup"));
400 * add positional features
402 SequenceFeature sf1 = new SequenceFeature("Pfam", "Desc", 10, 50, 0f,
405 groups = sf.getFeatureGroups(true);
406 assertEquals(groups.size(), 1);
407 assertTrue(groups.contains("PfamGroup"));
408 groups = sf.getFeatureGroups(false); // non-positional unchanged
409 assertEquals(groups.size(), 1);
410 assertTrue(groups.contains("AGroup"));
412 SequenceFeature sf2 = new SequenceFeature("Cath", "Desc", 10, 50, 0f,
415 groups = sf.getFeatureGroups(true);
416 assertEquals(groups.size(), 2);
417 assertTrue(groups.contains("PfamGroup"));
418 assertTrue(groups.contains(null));
422 assertTrue(sf.getFeatureGroups(true).isEmpty());
424 SequenceFeature sf3 = new SequenceFeature("CDS", "", 10, 50, 0f,
427 SequenceFeature sf4 = new SequenceFeature("exon", "", 10, 50, 0f,
430 groups = sf.getFeatureGroups(true);
431 assertEquals(groups.size(), 1);
432 assertTrue(groups.contains("Ensembl"));
435 * delete last Ensembl group feature from CDS features
436 * but still have one in exon features
439 groups = sf.getFeatureGroups(true);
440 assertEquals(groups.size(), 1);
441 assertTrue(groups.contains("Ensembl"));
444 * delete the last non-positional feature
447 groups = sf.getFeatureGroups(false);
448 assertTrue(groups.isEmpty());
451 @Test(groups = "Functional")
452 public void testGetFeatureTypesForGroups()
454 SequenceFeaturesI sf = new SequenceFeatures();
455 assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
458 * add feature with group = "Uniprot", type = "helix"
460 String groupUniprot = "Uniprot";
461 SequenceFeature sf1 = new SequenceFeature("helix", "Desc", 10, 50, 0f,
464 Set<String> groups = sf.getFeatureTypesForGroups(true, groupUniprot);
465 assertEquals(groups.size(), 1);
466 assertTrue(groups.contains("helix"));
467 assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
470 * add feature with group = "Uniprot", type = "strand"
472 SequenceFeature sf2 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
475 groups = sf.getFeatureTypesForGroups(true, groupUniprot);
476 assertEquals(groups.size(), 2);
477 assertTrue(groups.contains("helix"));
478 assertTrue(groups.contains("strand"));
481 * delete the "strand" Uniprot feature - still have "helix"
484 groups = sf.getFeatureTypesForGroups(true, groupUniprot);
485 assertEquals(groups.size(), 1);
486 assertTrue(groups.contains("helix"));
489 * delete the "helix" Uniprot feature - none left
492 assertTrue(sf.getFeatureTypesForGroups(true, groupUniprot).isEmpty());
495 * add some null group features
497 SequenceFeature sf3 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
500 SequenceFeature sf4 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
503 groups = sf.getFeatureTypesForGroups(true, (String) null);
504 assertEquals(groups.size(), 2);
505 assertTrue(groups.contains("strand"));
506 assertTrue(groups.contains("turn"));
509 * add strand/Cath and turn/Scop and query for one or both groups
510 * (find feature types for groups selected in Feature Settings)
512 SequenceFeature sf5 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
515 SequenceFeature sf6 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
518 groups = sf.getFeatureTypesForGroups(true, "Cath");
519 assertEquals(groups.size(), 1);
520 assertTrue(groups.contains("strand"));
521 groups = sf.getFeatureTypesForGroups(true, "Scop");
522 assertEquals(groups.size(), 1);
523 assertTrue(groups.contains("turn"));
524 groups = sf.getFeatureTypesForGroups(true, "Cath", "Scop");
525 assertEquals(groups.size(), 2);
526 assertTrue(groups.contains("turn"));
527 assertTrue(groups.contains("strand"));
528 // alternative vararg syntax
529 groups = sf.getFeatureTypesForGroups(true, new String[] { "Cath",
531 assertEquals(groups.size(), 2);
532 assertTrue(groups.contains("turn"));
533 assertTrue(groups.contains("strand"));
536 @Test(groups = "Functional")
537 public void testGetFeatureTypes()
539 SequenceFeaturesI store = new SequenceFeatures();
540 Set<String> types = store.getFeatureTypes();
541 assertTrue(types.isEmpty());
543 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
546 types = store.getFeatureTypes();
547 assertEquals(types.size(), 1);
548 assertTrue(types.contains("Metal"));
550 // null type is rejected...
551 SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
553 assertFalse(store.add(sf2));
554 types = store.getFeatureTypes();
555 assertEquals(types.size(), 1);
556 assertFalse(types.contains(null));
557 assertTrue(types.contains("Metal"));
560 * add non-positional feature
562 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
565 types = store.getFeatureTypes();
566 assertEquals(types.size(), 2);
567 assertTrue(types.contains("Pfam"));
570 * add contact feature
572 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
573 10, 20, Float.NaN, null);
575 types = store.getFeatureTypes();
576 assertEquals(types.size(), 3);
577 assertTrue(types.contains("Disulphide Bond"));
582 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
585 types = store.getFeatureTypes();
586 assertEquals(types.size(), 3); // unchanged
589 * delete first Pfam - still have one
591 assertTrue(store.delete(sf3));
592 types = store.getFeatureTypes();
593 assertEquals(types.size(), 3);
594 assertTrue(types.contains("Pfam"));
597 * delete second Pfam - no longer have one
599 assertTrue(store.delete(sf5));
600 types = store.getFeatureTypes();
601 assertEquals(types.size(), 2);
602 assertFalse(types.contains("Pfam"));
605 @Test(groups = "Functional")
606 public void testGetFeatureCount()
608 SequenceFeaturesI store = new SequenceFeatures();
609 assertEquals(store.getFeatureCount(true), 0);
610 assertEquals(store.getFeatureCount(false), 0);
615 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
618 assertEquals(store.getFeatureCount(true), 1);
619 assertEquals(store.getFeatureCount(false), 0);
622 * null feature type is rejected
624 SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
626 assertFalse(store.add(sf2));
627 assertEquals(store.getFeatureCount(true), 1);
628 assertEquals(store.getFeatureCount(false), 0);
631 * add non-positional feature
633 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
636 assertEquals(store.getFeatureCount(true), 1);
637 assertEquals(store.getFeatureCount(false), 1);
640 * add contact feature (counts as 1)
642 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
643 10, 20, Float.NaN, null);
645 assertEquals(store.getFeatureCount(true), 2);
646 assertEquals(store.getFeatureCount(false), 1);
649 * add another Pfam but this time as a positional feature
651 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
654 assertEquals(store.getFeatureCount(true), 3); // sf1, sf4, sf5
655 assertEquals(store.getFeatureCount(false), 1); // sf3
656 assertEquals(store.getFeatureCount(true, "Pfam"), 1); // positional
657 assertEquals(store.getFeatureCount(false, "Pfam"), 1); // non-positional
658 // search for type==null
659 assertEquals(store.getFeatureCount(true, (String) null), 0);
660 // search with no type specified
661 assertEquals(store.getFeatureCount(true, (String[]) null), 3);
662 assertEquals(store.getFeatureCount(true, "Metal", "Cath"), 1);
663 assertEquals(store.getFeatureCount(true, "Disulphide Bond"), 1);
664 assertEquals(store.getFeatureCount(true, "Metal", "Pfam", null), 2);
667 * delete first Pfam (non-positional)
669 assertTrue(store.delete(sf3));
670 assertEquals(store.getFeatureCount(true), 3);
671 assertEquals(store.getFeatureCount(false), 0);
674 * delete second Pfam (positional)
676 assertTrue(store.delete(sf5));
677 assertEquals(store.getFeatureCount(true), 2);
678 assertEquals(store.getFeatureCount(false), 0);
681 @Test(groups = "Functional")
682 public void testGetAllFeatures()
684 SequenceFeaturesI store = new SequenceFeatures();
685 List<SequenceFeature> features = store.getAllFeatures();
686 assertTrue(features.isEmpty());
688 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
691 features = store.getAllFeatures();
692 assertEquals(features.size(), 1);
693 assertTrue(features.contains(sf1));
695 SequenceFeature sf2 = new SequenceFeature("Metallic", "desc", 10, 20,
698 features = store.getAllFeatures();
699 assertEquals(features.size(), 2);
700 assertTrue(features.contains(sf2));
703 * add non-positional feature
705 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
708 features = store.getAllFeatures();
709 assertEquals(features.size(), 3);
710 assertTrue(features.contains(sf3));
713 * add contact feature
715 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
716 10, 20, Float.NaN, null);
718 features = store.getAllFeatures();
719 assertEquals(features.size(), 4);
720 assertTrue(features.contains(sf4));
725 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
728 features = store.getAllFeatures();
729 assertEquals(features.size(), 5);
730 assertTrue(features.contains(sf5));
733 * select by type does not apply to non-positional features
735 features = store.getAllFeatures("Cath");
736 assertEquals(features.size(), 1);
737 assertTrue(features.contains(sf3));
739 features = store.getAllFeatures("Pfam", "Cath", "Metal");
740 assertEquals(features.size(), 3);
741 assertTrue(features.contains(sf1));
742 assertTrue(features.contains(sf3));
743 assertTrue(features.contains(sf5));
748 assertTrue(store.delete(sf3));
749 features = store.getAllFeatures();
750 assertEquals(features.size(), 4);
751 assertFalse(features.contains(sf3));
756 assertTrue(store.delete(sf5));
757 features = store.getAllFeatures();
758 assertEquals(features.size(), 3);
759 assertFalse(features.contains(sf3));
762 @Test(groups = "Functional")
763 public void testGetTotalFeatureLength()
765 SequenceFeaturesI store = new SequenceFeatures();
766 assertEquals(store.getTotalFeatureLength(), 0);
768 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
770 assertTrue(store.add(sf1));
771 assertEquals(store.getTotalFeatureLength(), 11);
772 assertEquals(store.getTotalFeatureLength("Metal"), 11);
773 assertEquals(store.getTotalFeatureLength("Plastic"), 0);
775 // re-add does nothing!
776 assertFalse(store.add(sf1));
777 assertEquals(store.getTotalFeatureLength(), 11);
780 * add non-positional feature
782 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
785 assertEquals(store.getTotalFeatureLength(), 11);
788 * add contact feature - counts 1 to feature length
790 SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
791 10, 20, Float.NaN, null);
793 assertEquals(store.getTotalFeatureLength(), 12);
798 SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
801 assertEquals(store.getTotalFeatureLength(), 23);
806 assertTrue(store.delete(sf3)); // non-positional
807 assertEquals(store.getTotalFeatureLength(), 23); // no change
809 assertTrue(store.delete(sf5));
810 assertEquals(store.getTotalFeatureLength(), 12);
812 assertTrue(store.delete(sf4)); // contact
813 assertEquals(store.getTotalFeatureLength(), 11);
815 assertTrue(store.delete(sf1));
816 assertEquals(store.getTotalFeatureLength(), 0);
819 @Test(groups = "Functional")
820 public void testGetMinimumScore_getMaximumScore()
822 SequenceFeatures sf = new SequenceFeatures();
823 SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 0, 0,
824 Float.NaN, "group"); // non-positional, no score
826 SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 10, 20,
827 Float.NaN, "group"); // positional, no score
829 SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 10, 20, 1f,
832 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 12, 16, 4f,
835 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 0, 0, 11f,
838 SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, -7f,
842 assertEquals(sf.getMinimumScore("nosuchtype", true), Float.NaN);
843 assertEquals(sf.getMinimumScore("nosuchtype", false), Float.NaN);
844 assertEquals(sf.getMaximumScore("nosuchtype", true), Float.NaN);
845 assertEquals(sf.getMaximumScore("nosuchtype", false), Float.NaN);
847 // positional features min-max:
848 assertEquals(sf.getMinimumScore("Metal", true), 1f);
849 assertEquals(sf.getMaximumScore("Metal", true), 4f);
850 assertEquals(sf.getMinimumScore("Cath", true), Float.NaN);
851 assertEquals(sf.getMaximumScore("Cath", true), Float.NaN);
853 // non-positional features min-max:
854 assertEquals(sf.getMinimumScore("Cath", false), -7f);
855 assertEquals(sf.getMaximumScore("Cath", false), 11f);
856 assertEquals(sf.getMinimumScore("Metal", false), Float.NaN);
857 assertEquals(sf.getMaximumScore("Metal", false), Float.NaN);
859 // delete features; min-max should get recomputed
861 assertEquals(sf.getMinimumScore("Cath", false), 11f);
862 assertEquals(sf.getMaximumScore("Cath", false), 11f);
864 assertEquals(sf.getMinimumScore("Metal", true), 1f);
865 assertEquals(sf.getMaximumScore("Metal", true), 1f);
867 assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
868 assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
870 assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
871 assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
874 assertFalse(sf.hasFeatures());
875 assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
876 assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
877 assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
878 assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
881 @Test(groups = "Functional")
882 public void testVarargsToTypes()
884 SequenceFeatures sf = new SequenceFeatures();
885 sf.add(new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, "group"));
886 sf.add(new SequenceFeature("Cath", "desc", 10, 20, Float.NaN, "group"));
889 * no type specified - get all types stored
890 * they are returned in keyset (alphabetical) order
892 Map<String, FeatureStore> featureStores = (Map<String, FeatureStore>) PA
893 .getValue(sf, "featureStore");
895 Iterable<FeatureStore> types = sf.varargToTypes();
896 Iterator<FeatureStore> iterator = types.iterator();
897 assertTrue(iterator.hasNext());
898 assertSame(iterator.next(), featureStores.get("Cath"));
899 assertTrue(iterator.hasNext());
900 assertSame(iterator.next(), featureStores.get("Metal"));
901 assertFalse(iterator.hasNext());
904 * empty array is the same as no vararg parameter supplied
905 * so treated as all stored types
907 types = sf.varargToTypes(new String[] {});
908 iterator = types.iterator();
909 assertTrue(iterator.hasNext());
910 assertSame(iterator.next(), featureStores.get("Cath"));
911 assertTrue(iterator.hasNext());
912 assertSame(iterator.next(), featureStores.get("Metal"));
913 assertFalse(iterator.hasNext());
916 * null type specified; this is passed as vararg
919 types = sf.varargToTypes((String) null);
920 assertFalse(types.iterator().hasNext());
923 * null types array specified; this is passed as vararg null
925 types = sf.varargToTypes((String[]) null);
926 iterator = types.iterator();
927 assertTrue(iterator.hasNext());
928 assertSame(iterator.next(), featureStores.get("Cath"));
929 assertTrue(iterator.hasNext());
930 assertSame(iterator.next(), featureStores.get("Metal"));
931 assertFalse(iterator.hasNext());
936 types = sf.varargToTypes("Metal");
937 iterator = types.iterator();
938 assertTrue(iterator.hasNext());
939 assertSame(iterator.next(), featureStores.get("Metal"));
940 assertFalse(iterator.hasNext());
943 * two types specified - get sorted alphabetically
945 types = sf.varargToTypes("Metal", "Cath");
946 iterator = types.iterator();
947 assertTrue(iterator.hasNext());
948 assertSame(iterator.next(), featureStores.get("Cath"));
949 assertTrue(iterator.hasNext());
950 assertSame(iterator.next(), featureStores.get("Metal"));
951 assertFalse(iterator.hasNext());
954 * null type included - should be ignored
956 types = sf.varargToTypes("Metal", null, "Helix");
957 iterator = types.iterator();
958 assertTrue(iterator.hasNext());
959 assertSame(iterator.next(), featureStores.get("Metal"));
960 assertFalse(iterator.hasNext());
963 @Test(groups = "Functional")
964 public void testGetFeatureTypes_byOntology()
966 SequenceFeaturesI store = new SequenceFeatures();
968 SequenceFeature sf1 = new SequenceFeature("transcript", "desc", 10, 20,
971 // mRNA isA mature_transcript isA transcript
972 SequenceFeature sf2 = new SequenceFeature("mRNA", "desc", 10, 20,
975 // just to prove non-positional feature types are included
976 SequenceFeature sf3 = new SequenceFeature("mRNA", "desc", 0, 0,
979 SequenceFeature sf4 = new SequenceFeature("CDS", "desc", 0, 0,
983 Set<String> types = store.getFeatureTypes("transcript");
984 assertEquals(types.size(), 2);
985 assertTrue(types.contains("transcript"));
986 assertTrue(types.contains("mRNA"));
988 // matches include arguments whether SO terms or not
989 types = store.getFeatureTypes("transcript", "CDS");
990 assertEquals(types.size(), 3);
991 assertTrue(types.contains("transcript"));
992 assertTrue(types.contains("mRNA"));
993 assertTrue(types.contains("CDS"));
995 types = store.getFeatureTypes("exon");
996 assertTrue(types.isEmpty());
999 @Test(groups = "Functional")
1000 public void testGetFeaturesByOntology()
1002 SequenceFeaturesI store = new SequenceFeatures();
1003 List<SequenceFeature> features = store.getFeaturesByOntology();
1004 assertTrue(features.isEmpty());
1005 assertTrue(store.getFeaturesByOntology(new String[] {}).isEmpty());
1006 assertTrue(store.getFeaturesByOntology((String[]) null).isEmpty());
1008 SequenceFeature sf1 = new SequenceFeature("transcript", "desc", 10, 20,
1012 // mRNA isA transcript; added here 'as if' non-positional
1013 // just to show that non-positional features are included in results
1014 SequenceFeature sf2 = new SequenceFeature("mRNA", "desc", 0, 0,
1018 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 30, 40,
1022 features = store.getFeaturesByOntology("transcript");
1023 assertEquals(features.size(), 2);
1024 assertTrue(features.contains(sf1));
1025 assertTrue(features.contains(sf2));
1027 features = store.getFeaturesByOntology("mRNA");
1028 assertEquals(features.size(), 1);
1029 assertTrue(features.contains(sf2));
1031 features = store.getFeaturesByOntology("mRNA", "Pfam");
1032 assertEquals(features.size(), 2);
1033 assertTrue(features.contains(sf2));
1034 assertTrue(features.contains(sf3));
1036 features = store.getFeaturesByOntology("sequence_variant");
1037 assertTrue(features.isEmpty());
1040 @Test(groups = "Functional")
1041 public void testSortFeatures()
1043 List<SequenceFeature> sfs = new ArrayList<SequenceFeature>();
1044 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 30, 80,
1047 SequenceFeature sf2 = new SequenceFeature("Rfam", "desc", 40, 50,
1050 SequenceFeature sf3 = new SequenceFeature("Rfam", "desc", 50, 60,
1054 // sort by end position descending
1055 SequenceFeatures.sortFeatures(sfs, false);
1056 assertSame(sfs.get(0), sf1);
1057 assertSame(sfs.get(1), sf3);
1058 assertSame(sfs.get(2), sf2);
1060 // sort by start position ascending
1061 SequenceFeatures.sortFeatures(sfs, true);
1062 assertSame(sfs.get(0), sf1);
1063 assertSame(sfs.get(1), sf2);
1064 assertSame(sfs.get(2), sf3);
1067 @Test(groups = "Functional")
1068 public void testGetFeaturesForGroup()
1070 SequenceFeaturesI store = new SequenceFeatures();
1072 List<SequenceFeature> features = store.getFeaturesForGroup(true, null);
1073 assertTrue(features.isEmpty());
1074 assertTrue(store.getFeaturesForGroup(false, null).isEmpty());
1075 assertTrue(store.getFeaturesForGroup(true, "Uniprot").isEmpty());
1076 assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
1078 SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
1080 SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
1082 SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
1084 SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 0, 0, 0f,
1086 SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 5, 15, 0f,
1094 // positional features for null group, any type
1095 features = store.getFeaturesForGroup(true, null);
1096 assertEquals(features.size(), 2);
1097 assertTrue(features.contains(sf1));
1098 assertTrue(features.contains(sf5));
1100 // positional features for null group, specified type
1101 features = store.getFeaturesForGroup(true, null, new String[] { "Pfam",
1103 assertEquals(features.size(), 1);
1104 assertTrue(features.contains(sf1));
1105 features = store.getFeaturesForGroup(true, null, new String[] { "Pfam",
1107 assertEquals(features.size(), 2);
1108 assertTrue(features.contains(sf1));
1109 assertTrue(features.contains(sf5));
1111 // positional features for non-null group, any type
1112 features = store.getFeaturesForGroup(true, "Uniprot");
1113 assertEquals(features.size(), 1);
1114 assertTrue(features.contains(sf3));
1115 assertTrue(store.getFeaturesForGroup(true, "Rfam").isEmpty());
1117 // positional features for non-null group, specified type
1118 features = store.getFeaturesForGroup(true, "Uniprot", "Pfam", "Xfam",
1120 assertEquals(features.size(), 1);
1121 assertTrue(features.contains(sf3));
1122 assertTrue(store.getFeaturesForGroup(true, "Uniprot", "Cath").isEmpty());
1124 // non-positional features for null group, any type
1125 features = store.getFeaturesForGroup(false, null);
1126 assertEquals(features.size(), 1);
1127 assertTrue(features.contains(sf2));
1129 // non-positional features for null group, specified type
1130 features = store.getFeaturesForGroup(false, null, "Pfam", "Xfam");
1131 assertEquals(features.size(), 1);
1132 assertTrue(features.contains(sf2));
1133 assertTrue(store.getFeaturesForGroup(false, null, "Cath").isEmpty());
1135 // non-positional features for non-null group, any type
1136 features = store.getFeaturesForGroup(false, "Rfam");
1137 assertEquals(features.size(), 1);
1138 assertTrue(features.contains(sf4));
1139 assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
1141 // non-positional features for non-null group, specified type
1142 features = store.getFeaturesForGroup(false, "Rfam", "Pfam", "Metal");
1143 assertEquals(features.size(), 1);
1144 assertTrue(features.contains(sf4));
1145 assertTrue(store.getFeaturesForGroup(false, "Rfam", "Cath", "Pfam")
1149 @Test(groups = "Functional")
1150 public void testShiftFeatures()
1152 SequenceFeatures store = new SequenceFeatures();
1153 assertFalse(store.shiftFeatures(1));
1155 SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
1158 SequenceFeature sf2 = new SequenceFeature("Metal", "", 8, 14, 0f, null);
1161 SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
1164 // non-positional feature:
1165 SequenceFeature sf4 = new SequenceFeature("Pfam", "", 0, 0, 0f, null);
1169 * shift features right by 5
1171 assertTrue(store.shiftFeatures(5));
1173 // non-positional features untouched:
1174 List<SequenceFeature> nonPos = store.getNonPositionalFeatures();
1175 assertEquals(nonPos.size(), 1);
1176 assertTrue(nonPos.contains(sf4));
1178 // positional features are replaced
1179 List<SequenceFeature> pos = store.getPositionalFeatures();
1180 assertEquals(pos.size(), 3);
1181 assertFalse(pos.contains(sf1));
1182 assertFalse(pos.contains(sf2));
1183 assertFalse(pos.contains(sf3));
1184 SequenceFeatures.sortFeatures(pos, true); // ascending start pos
1185 assertEquals(pos.get(0).getBegin(), 7);
1186 assertEquals(pos.get(0).getEnd(), 10);
1187 assertEquals(pos.get(0).getType(), "Cath");
1188 assertEquals(pos.get(1).getBegin(), 13);
1189 assertEquals(pos.get(1).getEnd(), 19);
1190 assertEquals(pos.get(1).getType(), "Metal");
1191 assertEquals(pos.get(2).getBegin(), 28);
1192 assertEquals(pos.get(2).getEnd(), 37);
1193 assertEquals(pos.get(2).getType(), "Disulfide bond");
1196 * now shift left by 15
1197 * feature at [7-10] should be removed
1198 * feature at [13-19] should become [1-4]
1200 assertTrue(store.shiftFeatures(-15));
1201 pos = store.getPositionalFeatures();
1202 assertEquals(pos.size(), 2);
1203 SequenceFeatures.sortFeatures(pos, true);
1204 assertEquals(pos.get(0).getBegin(), 1);
1205 assertEquals(pos.get(0).getEnd(), 4);
1206 assertEquals(pos.get(0).getType(), "Metal");
1207 assertEquals(pos.get(1).getBegin(), 13);
1208 assertEquals(pos.get(1).getEnd(), 22);
1209 assertEquals(pos.get(1).getType(), "Disulfide bond");
1212 @Test(groups = "Functional")
1213 public void testIsOntologyTerm()
1215 SequenceFeatures store = new SequenceFeatures();
1216 assertTrue(store.isOntologyTerm("gobbledygook"));
1217 assertTrue(store.isOntologyTerm("transcript", "transcript"));
1218 assertTrue(store.isOntologyTerm("mRNA", "transcript"));
1219 assertFalse(store.isOntologyTerm("transcript", "mRNA"));
1220 assertTrue(store.isOntologyTerm("junk", "transcript", "junk"));
1221 assertTrue(store.isOntologyTerm("junk", new String[] {}));
1222 assertTrue(store.isOntologyTerm("junk", (String[]) null));