package jalview.datamodel.features; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import jalview.datamodel.SequenceFeature; import java.util.List; import java.util.Set; import org.testng.annotations.Test; public class SequenceFeaturesTest { @Test(groups = "Functional") public void testGetFeatures() { SequenceFeatures store = new SequenceFeatures(); SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20, Float.NaN, null); store.add(sf1); // same range, different description SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20, Float.NaN, null); store.add(sf2); // discontiguous range SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40, Float.NaN, null); store.add(sf3); // overlapping range SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35, Float.NaN, null); store.add(sf4); // enclosing range SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50, Float.NaN, null); store.add(sf5); // non-positional feature SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, null); store.add(sf6); // contact feature SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc", 18, 45, Float.NaN, null); store.add(sf7); // different feature type SequenceFeature sf8 = new SequenceFeature("Pfam", "desc", 30, 40, Float.NaN, null); store.add(sf8); SequenceFeature sf9 = new SequenceFeature("Pfam", "desc", 15, 35, Float.NaN, null); store.add(sf9); /* * get all features */ List features = store.getFeatures(); assertEquals(features.size(), 9); assertTrue(features.contains(sf1)); assertTrue(features.contains(sf2)); assertTrue(features.contains(sf3)); assertTrue(features.contains(sf4)); assertTrue(features.contains(sf5)); assertTrue(features.contains(sf6)); assertTrue(features.contains(sf7)); assertTrue(features.contains(sf8)); assertTrue(features.contains(sf9)); /* * get features by type */ assertTrue(store.getFeatures(null).isEmpty()); assertTrue(store.getFeatures("Cath").isEmpty()); assertTrue(store.getFeatures("METAL").isEmpty()); features = store.getFeatures("Metal"); assertEquals(features.size(), 6); assertTrue(features.contains(sf1)); assertTrue(features.contains(sf2)); assertTrue(features.contains(sf3)); assertTrue(features.contains(sf4)); assertTrue(features.contains(sf5)); assertTrue(features.contains(sf6)); features = store.getFeatures("Disulphide bond"); assertEquals(features.size(), 1); assertTrue(features.contains(sf7)); features = store.getFeatures("Pfam"); assertEquals(features.size(), 2); assertTrue(features.contains(sf8)); assertTrue(features.contains(sf9)); } @Test(groups = "Functional") public void testGetContactFeatures() { SequenceFeatures store = new SequenceFeatures(); // non-contact SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20, Float.NaN, null); store.add(sf1); // non-positional SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, null); store.add(sf2); // contact feature SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc", 18, 45, Float.NaN, null); store.add(sf3); // repeat for different feature type SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20, Float.NaN, null); store.add(sf4); SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0, Float.NaN, null); store.add(sf5); SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18, 45, Float.NaN, null); store.add(sf6); /* * get all contact features */ List features = store.getContactFeatures(); assertEquals(features.size(), 2); assertTrue(features.contains(sf3)); assertTrue(features.contains(sf6)); /* * get contact features by type */ assertTrue(store.getContactFeatures(null).isEmpty()); assertTrue(store.getContactFeatures("Cath").isEmpty()); assertTrue(store.getContactFeatures("Pfam").isEmpty()); assertTrue(store.getContactFeatures("DISULPHIDE BOND").isEmpty()); features = store.getContactFeatures("Disulphide bond"); assertEquals(features.size(), 1); assertTrue(features.contains(sf3)); features = store.getContactFeatures("Disulfide bond"); assertEquals(features.size(), 1); assertTrue(features.contains(sf6)); } @Test(groups = "Functional") public void testGetNonPositionalFeatures() { SequenceFeatures store = new SequenceFeatures(); // positional SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20, Float.NaN, null); store.add(sf1); // non-positional SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, null); store.add(sf2); // contact feature SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc", 18, 45, Float.NaN, null); store.add(sf3); // repeat for different feature type SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20, Float.NaN, null); store.add(sf4); SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0, Float.NaN, null); store.add(sf5); SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18, 45, Float.NaN, null); store.add(sf6); // one more non-positional, different description SequenceFeature sf7 = new SequenceFeature("Pfam", "desc2", 0, 0, Float.NaN, null); store.add(sf7); /* * get all non-positional features */ List features = store.getNonPositionalFeatures(); assertEquals(features.size(), 3); assertTrue(features.contains(sf2)); assertTrue(features.contains(sf5)); assertTrue(features.contains(sf7)); /* * get non-positional features by type */ assertTrue(store.getNonPositionalFeatures(null).isEmpty()); assertTrue(store.getNonPositionalFeatures("Cath").isEmpty()); assertTrue(store.getNonPositionalFeatures("PFAM").isEmpty()); features = store.getNonPositionalFeatures("Metal"); assertEquals(features.size(), 1); assertTrue(features.contains(sf2)); features = store.getNonPositionalFeatures("Pfam"); assertEquals(features.size(), 2); assertTrue(features.contains(sf5)); assertTrue(features.contains(sf7)); } /** * Helper method to add a feature of no particular type * * @param sf * @param type * @param from * @param to * @return */ SequenceFeature addFeature(SequenceFeatures sf, String type, int from, int to) { SequenceFeature sf1 = new SequenceFeature(type, "", from, to, Float.NaN, null); sf.add(sf1); return sf1; } @Test(groups = "Functional") public void testFindFeatures() { SequenceFeatures sf = new SequenceFeatures(); SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50); SequenceFeature sf2 = addFeature(sf, "Pfam", 1, 15); SequenceFeature sf3 = addFeature(sf, "Pfam", 20, 30); SequenceFeature sf4 = addFeature(sf, "Pfam", 40, 100); SequenceFeature sf5 = addFeature(sf, "Pfam", 60, 100); SequenceFeature sf6 = addFeature(sf, "Pfam", 70, 70); SequenceFeature sf7 = addFeature(sf, "Cath", 10, 50); SequenceFeature sf8 = addFeature(sf, "Cath", 1, 15); SequenceFeature sf9 = addFeature(sf, "Cath", 20, 30); SequenceFeature sf10 = addFeature(sf, "Cath", 40, 100); SequenceFeature sf11 = addFeature(sf, "Cath", 60, 100); SequenceFeature sf12 = addFeature(sf, "Cath", 70, 70); // null type is weird but possible: SequenceFeature sf13 = addFeature(sf, null, 5, 12); List overlaps = sf.findFeatures("Pfam", 200, 200); assertTrue(overlaps.isEmpty()); overlaps = sf.findFeatures("Pfam", 1, 9); assertEquals(overlaps.size(), 1); assertTrue(overlaps.contains(sf2)); overlaps = sf.findFeatures("Pfam", 5, 18); assertEquals(overlaps.size(), 2); assertTrue(overlaps.contains(sf1)); assertTrue(overlaps.contains(sf2)); overlaps = sf.findFeatures("Pfam", 30, 40); assertEquals(overlaps.size(), 3); assertTrue(overlaps.contains(sf1)); assertTrue(overlaps.contains(sf3)); assertTrue(overlaps.contains(sf4)); overlaps = sf.findFeatures("Pfam", 80, 90); assertEquals(overlaps.size(), 2); assertTrue(overlaps.contains(sf4)); assertTrue(overlaps.contains(sf5)); overlaps = sf.findFeatures("Pfam", 68, 70); assertEquals(overlaps.size(), 3); assertTrue(overlaps.contains(sf4)); assertTrue(overlaps.contains(sf5)); assertTrue(overlaps.contains(sf6)); overlaps = sf.findFeatures("Cath", 16, 69); assertEquals(overlaps.size(), 4); assertTrue(overlaps.contains(sf7)); assertFalse(overlaps.contains(sf8)); assertTrue(overlaps.contains(sf9)); assertTrue(overlaps.contains(sf10)); assertTrue(overlaps.contains(sf11)); assertFalse(overlaps.contains(sf12)); assertTrue(sf.findFeatures("Metal", 0, 1000).isEmpty()); overlaps = sf.findFeatures(null, 7, 7); assertEquals(overlaps.size(), 1); assertTrue(overlaps.contains(sf13)); } @Test(groups = "Functional") public void testDelete() { SequenceFeatures sf = new SequenceFeatures(); SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50); assertTrue(sf.getFeatures().contains(sf1)); assertFalse(sf.delete(null)); SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 15, 0f, null); assertFalse(sf.delete(sf2)); // not added, can't delete it assertTrue(sf.delete(sf1)); assertTrue(sf.getFeatures().isEmpty()); } @Test(groups = "Functional") public void testHasFeatures() { SequenceFeatures sf = new SequenceFeatures(); assertFalse(sf.hasFeatures()); SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50); assertTrue(sf.hasFeatures()); sf.delete(sf1); assertFalse(sf.hasFeatures()); } @Test(groups = "Functional") public void testGetFeatureGroups() { SequenceFeatures sf = new SequenceFeatures(); assertTrue(sf.getFeatureGroups().isEmpty()); SequenceFeature sf1 = new SequenceFeature("Pfam", "Desc", 10, 50, 0f, "PfamGroup"); sf.add(sf1); Set groups = sf.getFeatureGroups(); assertEquals(groups.size(), 1); assertTrue(groups.contains("PfamGroup")); SequenceFeature sf2 = new SequenceFeature("Cath", "Desc", 10, 50, 0f, null); sf.add(sf2); groups = sf.getFeatureGroups(); assertEquals(groups.size(), 2); assertTrue(groups.contains("PfamGroup")); assertTrue(groups.contains(null)); sf.delete(sf1); sf.delete(sf2); assertTrue(sf.getFeatureGroups().isEmpty()); SequenceFeature sf3 = new SequenceFeature("CDS", "", 10, 50, 0f, "Ensembl"); sf.add(sf3); SequenceFeature sf4 = new SequenceFeature("exon", "", 10, 50, 0f, "Ensembl"); sf.add(sf4); groups = sf.getFeatureGroups(); assertEquals(groups.size(), 1); assertTrue(groups.contains("Ensembl")); /* * delete last Ensembl group feature from CDS features * but still have one in exon features */ sf.delete(sf3); groups = sf.getFeatureGroups(); assertEquals(groups.size(), 1); assertTrue(groups.contains("Ensembl")); } }