package jalview.datamodel.features; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; import jalview.datamodel.SequenceFeature; import jalview.datamodel.features.FeatureStore.IntervalStoreType; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import org.testng.annotations.Test; import junit.extensions.PA; /** * Tests that exercise the 'NC array' implementation of IntervalStore */ public class FeatureStoreNCListBufferTest { private FeatureStore newFeatureStore() { return new FeatureStore(IntervalStoreType.INTERVAL_STORE_NCARRAY); } @Test(groups = "Functional") public void testFindFeatures_nonNested() { FeatureStore fs = newFeatureStore(); fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN, null)); // same range different description fs.addFeature(new SequenceFeature("", "desc", 10, 20, Float.NaN, null)); fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null)); fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null)); List overlaps = fs.findFeatures(1, 9); assertTrue(overlaps.isEmpty()); overlaps = fs.findFeatures(8, 10); assertEquals(overlaps.size(), 2); assertEquals(overlaps.get(0).getEnd(), 20); assertEquals(overlaps.get(1).getEnd(), 20); overlaps = fs.findFeatures(12, 16); assertEquals(overlaps.size(), 3); assertEquals(overlaps.get(0).getEnd(), 20); assertEquals(overlaps.get(1).getEnd(), 20); assertEquals(overlaps.get(2).getEnd(), 25); overlaps = fs.findFeatures(33, 33); assertEquals(overlaps.size(), 1); assertEquals(overlaps.get(0).getEnd(), 35); } @Test(groups = "Functional") public void testFindFeatures_nested() { FeatureStore fs = newFeatureStore(); SequenceFeature sf1 = addFeature(fs, 10, 50); SequenceFeature sf2 = addFeature(fs, 10, 40); SequenceFeature sf3 = addFeature(fs, 20, 30); // fudge feature at same location but different group (so is added) SequenceFeature sf4 = new SequenceFeature("", "", 20, 30, Float.NaN, "different group"); fs.addFeature(sf4); SequenceFeature sf5 = addFeature(fs, 35, 36); List overlaps = fs.findFeatures(1, 9); assertTrue(overlaps.isEmpty()); overlaps = fs.findFeatures(10, 15); assertEquals(overlaps.size(), 2); assertTrue(overlaps.contains(sf1)); assertTrue(overlaps.contains(sf2)); overlaps = fs.findFeatures(45, 60); assertEquals(overlaps.size(), 1); assertTrue(overlaps.contains(sf1)); overlaps = fs.findFeatures(32, 38); assertEquals(overlaps.size(), 3); assertTrue(overlaps.contains(sf1)); assertTrue(overlaps.contains(sf2)); assertTrue(overlaps.contains(sf5)); overlaps = fs.findFeatures(15, 25); assertEquals(overlaps.size(), 4); assertTrue(overlaps.contains(sf1)); assertTrue(overlaps.contains(sf2)); assertTrue(overlaps.contains(sf3)); assertTrue(overlaps.contains(sf4)); } @Test(groups = "Functional") public void testFindFeatures_mixed() { FeatureStore fs = newFeatureStore(); SequenceFeature sf1 = addFeature(fs, 10, 50); SequenceFeature sf2 = addFeature(fs, 1, 15); SequenceFeature sf3 = addFeature(fs, 20, 30); SequenceFeature sf4 = addFeature(fs, 40, 100); SequenceFeature sf5 = addFeature(fs, 60, 100); SequenceFeature sf6 = addFeature(fs, 70, 70); List overlaps = fs.findFeatures(200, 200); assertTrue(overlaps.isEmpty()); overlaps = fs.findFeatures(1, 9); assertEquals(overlaps.size(), 1); assertTrue(overlaps.contains(sf2)); overlaps = fs.findFeatures(5, 18); assertEquals(overlaps.size(), 2); assertTrue(overlaps.contains(sf1)); assertTrue(overlaps.contains(sf2)); overlaps = fs.findFeatures(30, 40); assertEquals(overlaps.size(), 3); assertTrue(overlaps.contains(sf1)); assertTrue(overlaps.contains(sf3)); assertTrue(overlaps.contains(sf4)); overlaps = fs.findFeatures(80, 90); assertEquals(overlaps.size(), 2); assertTrue(overlaps.contains(sf4)); assertTrue(overlaps.contains(sf5)); overlaps = fs.findFeatures(68, 70); assertEquals(overlaps.size(), 3); assertTrue(overlaps.contains(sf4)); assertTrue(overlaps.contains(sf5)); assertTrue(overlaps.contains(sf6)); } /** * Helper method to add a feature of no particular type * * @param fs * @param from * @param to * @return */ SequenceFeature addFeature(FeatureStore fs, int from, int to) { SequenceFeature sf1 = new SequenceFeature("", "", from, to, Float.NaN, null); fs.addFeature(sf1); return sf1; } @Test(groups = "Functional") public void testFindFeatures_contactFeatures() { FeatureStore fs = newFeatureStore(); SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10, 20, Float.NaN, null); fs.addFeature(sf); /* * neither contact point in range */ List overlaps = fs.findFeatures(1, 9); assertTrue(overlaps.isEmpty()); /* * neither contact point in range */ overlaps = fs.findFeatures(11, 19); assertTrue(overlaps.isEmpty()); /* * first contact point in range */ overlaps = fs.findFeatures(5, 15); assertEquals(overlaps.size(), 1); assertTrue(overlaps.contains(sf)); /* * second contact point in range */ overlaps = fs.findFeatures(15, 25); assertEquals(overlaps.size(), 1); assertTrue(overlaps.contains(sf)); /* * both contact points in range */ overlaps = fs.findFeatures(5, 25); assertEquals(overlaps.size(), 1); assertTrue(overlaps.contains(sf)); } @Test(groups = "Functional") public void testGetPositionalFeatures() { FeatureStore store = newFeatureStore(); SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20, Float.NaN, null); store.addFeature(sf1); // same range, different description SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20, Float.NaN, null); store.addFeature(sf2); // discontiguous range SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40, Float.NaN, null); store.addFeature(sf3); // overlapping range SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35, Float.NaN, null); store.addFeature(sf4); // enclosing range SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50, Float.NaN, null); store.addFeature(sf5); // non-positional feature SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, null); store.addFeature(sf6); // contact feature SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc", 18, 45, Float.NaN, null); store.addFeature(sf7); List features = store.getPositionalFeatures(); assertEquals(features.size(), 6); assertTrue(features.contains(sf1)); assertTrue(features.contains(sf2)); assertTrue(features.contains(sf3)); assertTrue(features.contains(sf4)); assertTrue(features.contains(sf5)); assertFalse(features.contains(sf6)); assertTrue(features.contains(sf7)); features = store.getNonPositionalFeatures(); assertEquals(features.size(), 1); assertTrue(features.contains(sf6)); } @Test(groups = "Functional") public void testDelete() { FeatureStore store = newFeatureStore(); SequenceFeature sf1 = addFeature(store, 10, 20); assertTrue(store.getPositionalFeatures().contains(sf1)); /* * simple deletion */ assertTrue(store.delete(sf1)); assertTrue(store.getPositionalFeatures().isEmpty()); /* * non-positional feature deletion */ SequenceFeature sf2 = addFeature(store, 0, 0); assertFalse(store.getPositionalFeatures().contains(sf2)); assertTrue(store.getNonPositionalFeatures().contains(sf2)); assertTrue(store.delete(sf2)); assertTrue(store.getNonPositionalFeatures().isEmpty()); /* * contact feature deletion */ SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11, 23, Float.NaN, null); store.addFeature(sf3); assertEquals(store.getPositionalFeatures().size(), 1); assertTrue(store.getPositionalFeatures().contains(sf3)); assertTrue(store.delete(sf3)); assertTrue(store.getPositionalFeatures().isEmpty()); /* * nested feature deletion */ SequenceFeature sf4 = addFeature(store, 20, 30); SequenceFeature sf5 = addFeature(store, 22, 26); // to NCList SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5 SequenceFeature sf7 = addFeature(store, 25, 25); // sibling of sf6 SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6 SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6 // SequenceFeature sf4 = addFeature(store, 20, 30); //// SequenceFeature sf5 = addFeature(store, 22, 26); ////// SequenceFeature sf6 = addFeature(store, 23, 24); // child of sf5 //////// SequenceFeature sf9 = addFeature(store, 23, 23); // child of sf6 //////// SequenceFeature sf8 = addFeature(store, 24, 24); // child of sf6 ////// SequenceFeature sf7 = addFeature(store, 25, 25); // child of sf5 // assertEquals(store.getPositionalFeatures().size(), 6); // delete a node with children - they take its place assertTrue(store.delete(sf6)); // sf8, sf9 should become children of sf5 assertEquals(store.getPositionalFeatures().size(), 5); assertFalse(store.getPositionalFeatures().contains(sf6)); // delete a node with no children assertTrue(store.delete(sf7)); assertEquals(store.getPositionalFeatures().size(), 4); assertFalse(store.getPositionalFeatures().contains(sf7)); // delete root of NCList assertTrue(store.delete(sf5)); assertEquals(store.getPositionalFeatures().size(), 3); assertFalse(store.getPositionalFeatures().contains(sf5)); // continue the killing fields assertTrue(store.delete(sf4)); assertEquals(store.getPositionalFeatures().size(), 2); assertFalse(store.getPositionalFeatures().contains(sf4)); assertTrue(store.delete(sf9)); assertEquals(store.getPositionalFeatures().size(), 1); assertFalse(store.getPositionalFeatures().contains(sf9)); assertTrue(store.delete(sf8)); assertTrue(store.getPositionalFeatures().isEmpty()); } @Test(groups = "Functional") public void testAddFeature() { FeatureStore fs = newFeatureStore(); SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN, null); SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20, Float.NaN, null); assertTrue(fs.addFeature(sf1)); assertEquals(fs.getFeatureCount(true), 1); // positional assertEquals(fs.getFeatureCount(false), 0); // non-positional /* * re-adding the same or an identical feature should fail */ assertFalse(fs.addFeature(sf1)); assertEquals(fs.getFeatureCount(true), 1); assertFalse(fs.addFeature(sf2)); assertEquals(fs.getFeatureCount(true), 1); /* * add non-positional */ SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null); assertTrue(fs.addFeature(sf3)); assertEquals(fs.getFeatureCount(true), 1); // positional assertEquals(fs.getFeatureCount(false), 1); // non-positional SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null); assertFalse(fs.addFeature(sf4)); // already stored assertEquals(fs.getFeatureCount(true), 1); // positional assertEquals(fs.getFeatureCount(false), 1); // non-positional /* * add contact */ SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 10, 20, Float.NaN, null); assertTrue(fs.addFeature(sf5)); assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact assertEquals(fs.getFeatureCount(false), 1); // non-positional SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 10, 20, Float.NaN, null); assertFalse(fs.addFeature(sf6)); // already stored assertEquals(fs.getFeatureCount(true), 2); // no change assertEquals(fs.getFeatureCount(false), 1); // no change } @Test(groups = "Functional") public void testIsEmpty() { FeatureStore fs = newFeatureStore(); assertTrue(fs.isEmpty()); assertEquals(fs.getFeatureCount(true), 0); /* * non-nested feature */ SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN, null); fs.addFeature(sf1); assertFalse(fs.isEmpty()); assertEquals(fs.getFeatureCount(true), 1); fs.delete(sf1); assertTrue(fs.isEmpty()); assertEquals(fs.getFeatureCount(true), 0); /* * non-positional feature */ sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null); fs.addFeature(sf1); assertFalse(fs.isEmpty()); assertEquals(fs.getFeatureCount(false), 1); // non-positional assertEquals(fs.getFeatureCount(true), 0); // positional fs.delete(sf1); assertTrue(fs.isEmpty()); assertEquals(fs.getFeatureCount(false), 0); /* * contact feature */ sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null); fs.addFeature(sf1); assertFalse(fs.isEmpty()); assertEquals(fs.getFeatureCount(true), 1); fs.delete(sf1); assertTrue(fs.isEmpty()); assertEquals(fs.getFeatureCount(true), 0); /* * sf2, sf3 added as nested features */ sf1 = new SequenceFeature("Cath", "", 19, 49, Float.NaN, null); SequenceFeature sf2 = new SequenceFeature("Cath", "", 20, 40, Float.NaN, null); SequenceFeature sf3 = new SequenceFeature("Cath", "", 25, 35, Float.NaN, null); fs.addFeature(sf1); fs.addFeature(sf2); fs.addFeature(sf3); assertEquals(fs.getFeatureCount(true), 3); assertTrue(fs.delete(sf1)); assertEquals(fs.getFeatureCount(true), 2); Collection intervalStore = (Collection) PA .getValue(fs, "features"); assertEquals(intervalStore.size(), 2); assertFalse(fs.isEmpty()); assertTrue(fs.delete(sf2)); assertEquals(fs.getFeatureCount(true), 1); assertFalse(fs.isEmpty()); assertTrue(fs.delete(sf3)); assertEquals(fs.getFeatureCount(true), 0); assertTrue(fs.isEmpty()); // all gone } @Test(groups = "Functional") public void testGetFeatureGroups() { FeatureStore fs = newFeatureStore(); assertTrue(fs.getFeatureGroups(true).isEmpty()); assertTrue(fs.getFeatureGroups(false).isEmpty()); SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1"); fs.addFeature(sf1); Set groups = fs.getFeatureGroups(true); assertEquals(groups.size(), 1); assertTrue(groups.contains("group1")); /* * add another feature of the same group, delete one, delete both */ SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1"); fs.addFeature(sf2); groups = fs.getFeatureGroups(true); assertEquals(groups.size(), 1); assertTrue(groups.contains("group1")); fs.delete(sf2); groups = fs.getFeatureGroups(true); assertEquals(groups.size(), 1); assertTrue(groups.contains("group1")); fs.delete(sf1); groups = fs.getFeatureGroups(true); assertTrue(fs.getFeatureGroups(true).isEmpty()); SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2"); fs.addFeature(sf3); SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2"); fs.addFeature(sf4); SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null); fs.addFeature(sf5); groups = fs.getFeatureGroups(true); assertEquals(groups.size(), 3); assertTrue(groups.contains("group2")); assertTrue(groups.contains("Group2")); // case sensitive assertTrue(groups.contains(null)); // null allowed assertTrue(fs.getFeatureGroups(false).isEmpty()); // non-positional fs.delete(sf3); groups = fs.getFeatureGroups(true); assertEquals(groups.size(), 2); assertFalse(groups.contains("group2")); fs.delete(sf4); groups = fs.getFeatureGroups(true); assertEquals(groups.size(), 1); assertFalse(groups.contains("Group2")); fs.delete(sf5); groups = fs.getFeatureGroups(true); assertTrue(groups.isEmpty()); /* * add non-positional feature */ SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, 1f, "CathGroup"); fs.addFeature(sf6); groups = fs.getFeatureGroups(false); assertEquals(groups.size(), 1); assertTrue(groups.contains("CathGroup")); assertTrue(fs.delete(sf6)); assertTrue(fs.getFeatureGroups(false).isEmpty()); } @Test(groups = "Functional") public void testGetTotalFeatureLength() { FeatureStore fs = newFeatureStore(); assertEquals(fs.getTotalFeatureLength(), 0); addFeature(fs, 10, 20); // 11 assertEquals(fs.getTotalFeatureLength(), 11); addFeature(fs, 17, 37); // 21 SequenceFeature sf1 = addFeature(fs, 14, 74); // 61 assertEquals(fs.getTotalFeatureLength(), 93); // non-positional features don't count SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f, "group1"); fs.addFeature(sf2); assertEquals(fs.getTotalFeatureLength(), 93); // contact features count 1 SequenceFeature sf3 = new SequenceFeature("disulphide bond", "desc", 15, 35, 1f, "group1"); fs.addFeature(sf3); assertEquals(fs.getTotalFeatureLength(), 94); assertTrue(fs.delete(sf1)); assertEquals(fs.getTotalFeatureLength(), 33); assertFalse(fs.delete(sf1)); assertEquals(fs.getTotalFeatureLength(), 33); assertTrue(fs.delete(sf2)); assertEquals(fs.getTotalFeatureLength(), 33); assertTrue(fs.delete(sf3)); assertEquals(fs.getTotalFeatureLength(), 32); } @Test(groups = "Functional") public void testGetFeatureLength() { /* * positional feature */ SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1"); assertEquals(FeatureStore.getFeatureLength(sf1), 11); /* * non-positional feature */ SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 0, 0, 1f, "CathGroup"); assertEquals(FeatureStore.getFeatureLength(sf2), 0); /* * contact feature counts 1 */ SequenceFeature sf3 = new SequenceFeature("Disulphide Bond", "desc", 14, 28, 1f, "AGroup"); assertEquals(FeatureStore.getFeatureLength(sf3), 1); } @Test(groups = "Functional") public void testMin() { assertEquals(FeatureStore.min(Float.NaN, Float.NaN), Float.NaN); assertEquals(FeatureStore.min(Float.NaN, 2f), 2f); assertEquals(FeatureStore.min(-2f, Float.NaN), -2f); assertEquals(FeatureStore.min(2f, -3f), -3f); } @Test(groups = "Functional") public void testMax() { assertEquals(FeatureStore.max(Float.NaN, Float.NaN), Float.NaN); assertEquals(FeatureStore.max(Float.NaN, 2f), 2f); assertEquals(FeatureStore.max(-2f, Float.NaN), -2f); assertEquals(FeatureStore.max(2f, -3f), 2f); } @Test(groups = "Functional") public void testGetMinimumScore_getMaximumScore() { FeatureStore fs = newFeatureStore(); assertEquals(fs.getMinimumScore(true), Float.NaN); // positional assertEquals(fs.getMaximumScore(true), Float.NaN); assertEquals(fs.getMinimumScore(false), Float.NaN); // non-positional assertEquals(fs.getMaximumScore(false), Float.NaN); // add features with no score SequenceFeature sf1 = new SequenceFeature("type", "desc", 0, 0, Float.NaN, "group"); fs.addFeature(sf1); SequenceFeature sf2 = new SequenceFeature("type", "desc", 10, 20, Float.NaN, "group"); fs.addFeature(sf2); assertEquals(fs.getMinimumScore(true), Float.NaN); assertEquals(fs.getMaximumScore(true), Float.NaN); assertEquals(fs.getMinimumScore(false), Float.NaN); assertEquals(fs.getMaximumScore(false), Float.NaN); // add positional features with score SequenceFeature sf3 = new SequenceFeature("type", "desc", 10, 20, 1f, "group"); fs.addFeature(sf3); SequenceFeature sf4 = new SequenceFeature("type", "desc", 12, 16, 4f, "group"); fs.addFeature(sf4); assertEquals(fs.getMinimumScore(true), 1f); assertEquals(fs.getMaximumScore(true), 4f); assertEquals(fs.getMinimumScore(false), Float.NaN); assertEquals(fs.getMaximumScore(false), Float.NaN); // add non-positional features with score SequenceFeature sf5 = new SequenceFeature("type", "desc", 0, 0, 11f, "group"); fs.addFeature(sf5); SequenceFeature sf6 = new SequenceFeature("type", "desc", 0, 0, -7f, "group"); fs.addFeature(sf6); assertEquals(fs.getMinimumScore(true), 1f); assertEquals(fs.getMaximumScore(true), 4f); assertEquals(fs.getMinimumScore(false), -7f); assertEquals(fs.getMaximumScore(false), 11f); // delete one positional and one non-positional // min-max should be recomputed assertTrue(fs.delete(sf6)); assertTrue(fs.delete(sf3)); assertEquals(fs.getMinimumScore(true), 4f); assertEquals(fs.getMaximumScore(true), 4f); assertEquals(fs.getMinimumScore(false), 11f); assertEquals(fs.getMaximumScore(false), 11f); // delete remaining features with score assertTrue(fs.delete(sf4)); assertTrue(fs.delete(sf5)); assertEquals(fs.getMinimumScore(true), Float.NaN); assertEquals(fs.getMaximumScore(true), Float.NaN); assertEquals(fs.getMinimumScore(false), Float.NaN); assertEquals(fs.getMaximumScore(false), Float.NaN); // delete all features assertTrue(fs.delete(sf1)); assertTrue(fs.delete(sf2)); assertTrue(fs.isEmpty()); assertEquals(fs.getMinimumScore(true), Float.NaN); assertEquals(fs.getMaximumScore(true), Float.NaN); assertEquals(fs.getMinimumScore(false), Float.NaN); assertEquals(fs.getMaximumScore(false), Float.NaN); } @Test(groups = "Functional") public void testListContains() { FeatureStore featureStore = newFeatureStore(); assertFalse(featureStore.listContains(null, null)); List features = new ArrayList<>(); assertFalse(featureStore.listContains(features, null)); SequenceFeature sf1 = new SequenceFeature("type1", "desc1", 20, 30, 3f, "group1"); assertFalse(featureStore.listContains(null, sf1)); assertFalse(featureStore.listContains(features, sf1)); features.add(sf1); SequenceFeature sf2 = new SequenceFeature("type1", "desc1", 20, 30, 3f, "group1"); SequenceFeature sf3 = new SequenceFeature("type1", "desc1", 20, 40, 3f, "group1"); // sf2.equals(sf1) so contains should return true assertTrue(featureStore.listContains(features, sf2)); assertFalse(featureStore.listContains(features, sf3)); } @Test(groups = "Functional") public void testGetFeaturesForGroup() { FeatureStore fs = newFeatureStore(); /* * with no features */ assertTrue(fs.getFeaturesForGroup(true, null).isEmpty()); assertTrue(fs.getFeaturesForGroup(false, null).isEmpty()); assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty()); assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty()); /* * sf1: positional feature in the null group */ SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f, null); fs.addFeature(sf1); assertTrue(fs.getFeaturesForGroup(true, "uniprot").isEmpty()); assertTrue(fs.getFeaturesForGroup(false, "uniprot").isEmpty()); assertTrue(fs.getFeaturesForGroup(false, null).isEmpty()); List features = fs.getFeaturesForGroup(true, null); assertEquals(features.size(), 1); assertTrue(features.contains(sf1)); /* * sf2: non-positional feature in the null group * sf3: positional feature in a non-null group * sf4: non-positional feature in a non-null group */ SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f, null); SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f, "Uniprot"); SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 0, 0, 0f, "Rfam"); fs.addFeature(sf2); fs.addFeature(sf3); fs.addFeature(sf4); features = fs.getFeaturesForGroup(true, null); assertEquals(features.size(), 1); assertTrue(features.contains(sf1)); features = fs.getFeaturesForGroup(false, null); assertEquals(features.size(), 1); assertTrue(features.contains(sf2)); features = fs.getFeaturesForGroup(true, "Uniprot"); assertEquals(features.size(), 1); assertTrue(features.contains(sf3)); features = fs.getFeaturesForGroup(false, "Rfam"); assertEquals(features.size(), 1); assertTrue(features.contains(sf4)); } @Test(groups = "Functional") public void testShiftFeatures() { FeatureStore fs = newFeatureStore(); assertFalse(fs.shiftFeatures(0, 1)); // nothing to do SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null); fs.addFeature(sf1); // nested feature: SequenceFeature sf2 = new SequenceFeature("Cath", "", 8, 14, 0f, null); fs.addFeature(sf2); // contact feature: SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32, 0f, null); fs.addFeature(sf3); // non-positional feature: SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, null); fs.addFeature(sf4); /* * shift all features right by 5 */ assertTrue(fs.shiftFeatures(0, 5)); // non-positional features untouched: List nonPos = fs.getNonPositionalFeatures(); assertEquals(nonPos.size(), 1); assertTrue(nonPos.contains(sf4)); // positional features are replaced List pos = fs.getPositionalFeatures(); assertEquals(pos.size(), 3); assertFalse(pos.contains(sf1)); assertFalse(pos.contains(sf2)); assertFalse(pos.contains(sf3)); SequenceFeatures.sortFeatures(pos, true); // ascending start pos assertEquals(pos.get(0).getBegin(), 7); assertEquals(pos.get(0).getEnd(), 10); assertEquals(pos.get(1).getBegin(), 13); assertEquals(pos.get(1).getEnd(), 19); assertEquals(pos.get(2).getBegin(), 28); assertEquals(pos.get(2).getEnd(), 37); /* * now shift left by 15 * feature at [7-10] should be removed * feature at [13-19] should become [1-4] */ assertTrue(fs.shiftFeatures(0, -15)); pos = fs.getPositionalFeatures(); assertEquals(pos.size(), 2); SequenceFeatures.sortFeatures(pos, true); assertEquals(pos.get(0).getBegin(), 1); assertEquals(pos.get(0).getEnd(), 4); assertEquals(pos.get(1).getBegin(), 13); assertEquals(pos.get(1).getEnd(), 22); /* * shift right by 4 from position 2 onwards * feature at [1-4] unchanged, feature at [13-22] shifts */ assertTrue(fs.shiftFeatures(2, 4)); pos = fs.getPositionalFeatures(); assertEquals(pos.size(), 2); SequenceFeatures.sortFeatures(pos, true); assertEquals(pos.get(0).getBegin(), 1); assertEquals(pos.get(0).getEnd(), 4); assertEquals(pos.get(1).getBegin(), 17); assertEquals(pos.get(1).getEnd(), 26); /* * shift right by 4 from position 18 onwards * should be no change */ SequenceFeature f1 = pos.get(0); SequenceFeature f2 = pos.get(1); assertFalse(fs.shiftFeatures(18, 4)); // no update pos = fs.getPositionalFeatures(); assertEquals(pos.size(), 2); SequenceFeatures.sortFeatures(pos, true); assertSame(pos.get(0), f1); assertSame(pos.get(1), f2); } @Test(groups = "Functional") public void testDelete_readd() { /* * add a feature and a nested feature */ FeatureStore store = newFeatureStore(); SequenceFeature sf1 = addFeature(store, 10, 20); // sf2 is nested in sf1 so will be stored in nestedFeatures SequenceFeature sf2 = addFeature(store, 12, 14); List features = store.getPositionalFeatures(); assertEquals(features.size(), 2); assertTrue(features.contains(sf1)); assertTrue(features.contains(sf2)); Collection intervalStore = (Collection) PA .getValue(store, "features"); assertTrue(intervalStore.contains(sf1)); assertTrue(intervalStore.contains(sf2)); /* * delete the first feature */ assertTrue(store.delete(sf1)); features = store.getPositionalFeatures(); assertFalse(features.contains(sf1)); assertTrue(features.contains(sf2)); /* * re-add the 'nested' feature; is it now duplicated? */ store.addFeature(sf2); features = store.getPositionalFeatures(); assertEquals(features.size(), 1); assertTrue(features.contains(sf2)); } @Test(groups = "Functional") public void testContains() { FeatureStore fs = newFeatureStore(); SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20, Float.NaN, "group1"); SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20, Float.NaN, "group2"); SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, "group1"); SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f, "group1"); SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15, Float.NaN, "group1"); SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15, Float.NaN, "group2"); fs.addFeature(sf1); fs.addFeature(sf3); fs.addFeature(sf5); assertTrue(fs.contains(sf1)); // positional feature assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature assertFalse(fs.contains(sf2)); // different group assertTrue(fs.contains(sf3)); // non-positional assertTrue(fs.contains(new SequenceFeature(sf3))); assertFalse(fs.contains(sf4)); // different score assertTrue(fs.contains(sf5)); // contact feature assertTrue(fs.contains(new SequenceFeature(sf5))); assertFalse(fs.contains(sf6)); // different group /* * add a nested feature */ SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16, Float.NaN, "group1"); fs.addFeature(sf7); assertTrue(fs.contains(sf7)); assertTrue(fs.contains(new SequenceFeature(sf7))); /* * delete the outer (enclosing, non-nested) feature */ fs.delete(sf1); assertFalse(fs.contains(sf1)); assertTrue(fs.contains(sf7)); } }