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 static org.testng.Assert.fail;
import jalview.datamodel.SequenceFeature;
+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;
+
public class FeatureStoreTest
{
+ private FeatureStore newFeatureStore()
+ {
+ return new FeatureStore();
+ }
@Test(groups = "Functional")
public void testFindFeatures_nonNested()
{
- FeatureStore fs = new FeatureStore();
+ FeatureStore fs = newFeatureStore();
fs.addFeature(new SequenceFeature("", "", 10, 20, Float.NaN,
null));
// same range different description
fs.addFeature(new SequenceFeature("", "", 15, 25, Float.NaN, null));
fs.addFeature(new SequenceFeature("", "", 20, 35, Float.NaN, null));
- List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+ List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
assertTrue(overlaps.isEmpty());
- overlaps = fs.findOverlappingFeatures(8, 10);
+ overlaps = fs.findFeatures(8, 10);
assertEquals(overlaps.size(), 2);
assertEquals(overlaps.get(0).getEnd(), 20);
assertEquals(overlaps.get(1).getEnd(), 20);
- overlaps = fs.findOverlappingFeatures(12, 16);
+ 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.findOverlappingFeatures(33, 33);
+ overlaps = fs.findFeatures(33, 33);
assertEquals(overlaps.size(), 1);
assertEquals(overlaps.get(0).getEnd(), 35);
}
@Test(groups = "Functional")
public void testFindFeatures_nested()
{
- FeatureStore fs = new FeatureStore();
+ FeatureStore fs = newFeatureStore();
SequenceFeature sf1 = addFeature(fs, 10, 50);
SequenceFeature sf2 = addFeature(fs, 10, 40);
SequenceFeature sf3 = addFeature(fs, 20, 30);
fs.addFeature(sf4);
SequenceFeature sf5 = addFeature(fs, 35, 36);
- List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+ List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
assertTrue(overlaps.isEmpty());
- overlaps = fs.findOverlappingFeatures(10, 15);
+ overlaps = fs.findFeatures(10, 15);
assertEquals(overlaps.size(), 2);
assertTrue(overlaps.contains(sf1));
assertTrue(overlaps.contains(sf2));
- overlaps = fs.findOverlappingFeatures(45, 60);
+ overlaps = fs.findFeatures(45, 60);
assertEquals(overlaps.size(), 1);
assertTrue(overlaps.contains(sf1));
- overlaps = fs.findOverlappingFeatures(32, 38);
+ overlaps = fs.findFeatures(32, 38);
assertEquals(overlaps.size(), 3);
assertTrue(overlaps.contains(sf1));
assertTrue(overlaps.contains(sf2));
assertTrue(overlaps.contains(sf5));
- overlaps = fs.findOverlappingFeatures(15, 25);
+ overlaps = fs.findFeatures(15, 25);
assertEquals(overlaps.size(), 4);
assertTrue(overlaps.contains(sf1));
assertTrue(overlaps.contains(sf2));
@Test(groups = "Functional")
public void testFindFeatures_mixed()
{
- FeatureStore fs = new FeatureStore();
+ FeatureStore fs = newFeatureStore();
SequenceFeature sf1 = addFeature(fs, 10, 50);
SequenceFeature sf2 = addFeature(fs, 1, 15);
SequenceFeature sf3 = addFeature(fs, 20, 30);
SequenceFeature sf5 = addFeature(fs, 60, 100);
SequenceFeature sf6 = addFeature(fs, 70, 70);
- List<SequenceFeature> overlaps = fs.findOverlappingFeatures(200, 200);
+ List<SequenceFeature> overlaps = fs.findFeatures(200, 200);
assertTrue(overlaps.isEmpty());
- overlaps = fs.findOverlappingFeatures(1, 9);
+ overlaps = fs.findFeatures(1, 9);
assertEquals(overlaps.size(), 1);
assertTrue(overlaps.contains(sf2));
- overlaps = fs.findOverlappingFeatures(5, 18);
+ overlaps = fs.findFeatures(5, 18);
assertEquals(overlaps.size(), 2);
assertTrue(overlaps.contains(sf1));
assertTrue(overlaps.contains(sf2));
- overlaps = fs.findOverlappingFeatures(30, 40);
+ overlaps = fs.findFeatures(30, 40);
assertEquals(overlaps.size(), 3);
assertTrue(overlaps.contains(sf1));
assertTrue(overlaps.contains(sf3));
assertTrue(overlaps.contains(sf4));
- overlaps = fs.findOverlappingFeatures(80, 90);
+ overlaps = fs.findFeatures(80, 90);
assertEquals(overlaps.size(), 2);
assertTrue(overlaps.contains(sf4));
assertTrue(overlaps.contains(sf5));
- overlaps = fs.findOverlappingFeatures(68, 70);
+ overlaps = fs.findFeatures(68, 70);
assertEquals(overlaps.size(), 3);
assertTrue(overlaps.contains(sf4));
assertTrue(overlaps.contains(sf5));
@Test(groups = "Functional")
public void testFindFeatures_contactFeatures()
{
- FeatureStore fs = new FeatureStore();
+ FeatureStore fs = newFeatureStore();
SequenceFeature sf = new SequenceFeature("disulphide bond", "bond", 10,
20, Float.NaN, null);
/*
* neither contact point in range
*/
- List<SequenceFeature> overlaps = fs.findOverlappingFeatures(1, 9);
+ List<SequenceFeature> overlaps = fs.findFeatures(1, 9);
assertTrue(overlaps.isEmpty());
/*
* neither contact point in range
*/
- overlaps = fs.findOverlappingFeatures(11, 19);
+ overlaps = fs.findFeatures(11, 19);
assertTrue(overlaps.isEmpty());
/*
* first contact point in range
*/
- overlaps = fs.findOverlappingFeatures(5, 15);
+ overlaps = fs.findFeatures(5, 15);
assertEquals(overlaps.size(), 1);
assertTrue(overlaps.contains(sf));
/*
* second contact point in range
*/
- overlaps = fs.findOverlappingFeatures(15, 25);
+ overlaps = fs.findFeatures(15, 25);
assertEquals(overlaps.size(), 1);
assertTrue(overlaps.contains(sf));
/*
* both contact points in range
*/
- overlaps = fs.findOverlappingFeatures(5, 25);
+ overlaps = fs.findFeatures(5, 25);
assertEquals(overlaps.size(), 1);
assertTrue(overlaps.contains(sf));
}
- /**
- * Tests for the method that returns false for an attempt to add a feature
- * that would enclose, or be enclosed by, another feature
- */
@Test(groups = "Functional")
- public void testAddNonNestedFeature()
+ public void testGetPositionalFeatures_withResultList()
{
- FeatureStore fs = new FeatureStore();
-
- String type = "Domain";
- SequenceFeature sf1 = new SequenceFeature(type, type, 10, 20,
+ FeatureStore store = newFeatureStore();
+ SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
Float.NaN, null);
- assertTrue(fs.addNonNestedFeature(sf1));
+ store.addFeature(sf1);
+ // contact feature
+ SequenceFeature sf2 = new SequenceFeature("Disulphide bond", "desc", 18,
+ 45, Float.NaN, null);
+ store.addFeature(sf2);
- // co-located feature is ok
- SequenceFeature sf2 = new SequenceFeature(type, type, 10, 20,
- Float.NaN, null);
- assertTrue(fs.addNonNestedFeature(sf2));
+ List<SequenceFeature> features = new ArrayList<>();
+ store.getPositionalFeatures(features);
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(sf1));
+ assertTrue(features.contains(sf2));
- // overlap left is ok
- SequenceFeature sf3 = new SequenceFeature(type, type, 5, 15, Float.NaN,
- null);
- assertTrue(fs.addNonNestedFeature(sf3));
+ /*
+ * no check for duplicates
+ */
+ features.remove(sf1);
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf2));
+ store.getPositionalFeatures(features);
+ assertEquals(features.size(), 3);
+ assertTrue(features.contains(sf1));
+ assertTrue(features.contains(sf2)); // two copies now
+ features.remove(sf2);
+ assertTrue(features.contains(sf2)); // one copy left
+ assertEquals(features.size(), 2);
- // overlap right is ok
- SequenceFeature sf4 = new SequenceFeature(type, type, 15, 25,
- Float.NaN, null);
- assertTrue(fs.addNonNestedFeature(sf4));
+ /*
+ * null argument throws exception
+ */
+ try
+ {
+ store.getPositionalFeatures(null);
+ fail("expected exception");
+ } catch (NullPointerException e)
+ {
+ // expected
+ }
+ }
- // add enclosing feature is not ok
- SequenceFeature sf5 = new SequenceFeature(type, type, 10, 21,
- Float.NaN, null);
- assertFalse(fs.addNonNestedFeature(sf5));
- SequenceFeature sf6 = new SequenceFeature(type, type, 4, 15, Float.NaN,
- null);
- assertFalse(fs.addNonNestedFeature(sf6));
- SequenceFeature sf7 = new SequenceFeature(type, type, 1, 50, Float.NaN,
- null);
- assertFalse(fs.addNonNestedFeature(sf7));
+ @Test(groups = "Functional")
+ public void testGetNonPositionalFeatures()
+ {
+ FeatureStore store = newFeatureStore();
+ List<SequenceFeature> features = store.getNonPositionalFeatures();
+ assertTrue(features.isEmpty());
- // add enclosed feature is not ok
- SequenceFeature sf8 = new SequenceFeature(type, type, 10, 19,
+ SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
Float.NaN, null);
- assertFalse(fs.addNonNestedFeature(sf8));
- SequenceFeature sf9 = new SequenceFeature(type, type, 16, 25,
+ store.addFeature(sf1);
+ assertTrue(features.isEmpty());
+
+ SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
Float.NaN, null);
- assertFalse(fs.addNonNestedFeature(sf9));
- SequenceFeature sf10 = new SequenceFeature(type, type, 7, 7, Float.NaN,
- null);
- assertFalse(fs.addNonNestedFeature(sf10));
+ store.addFeature(sf2);
+ features = store.getNonPositionalFeatures();
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf2));
+
+ /*
+ * with result list argument
+ */
+ features.clear();
+ store.getNonPositionalFeatures(features);
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf2));
+
+ /*
+ * no check for duplicates
+ */
+ store.getNonPositionalFeatures(features);
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(sf2)); // two copies
+ features.remove(sf2);
+ assertTrue(features.contains(sf2));
+
+ /*
+ * null argument throws exception
+ */
+ try
+ {
+ store.getNonPositionalFeatures(null);
+ fail("expected exception");
+ } catch (NullPointerException e)
+ {
+ // expected
+ }
}
@Test(groups = "Functional")
- public void testGetFeatures()
+ public void testGetPositionalFeatures()
{
- FeatureStore store = new FeatureStore();
+ FeatureStore store = newFeatureStore();
SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
Float.NaN, null);
store.addFeature(sf1);
18, 45, Float.NaN, null);
store.addFeature(sf7);
- List<SequenceFeature> features = store.getFeatures();
- assertEquals(features.size(), 7);
+ List<SequenceFeature> 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));
- assertTrue(features.contains(sf6));
+ 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 = new FeatureStore();
+ FeatureStore store = newFeatureStore();
SequenceFeature sf1 = addFeature(store, 10, 20);
- assertTrue(store.getFeatures().contains(sf1));
+ assertTrue(store.getPositionalFeatures().contains(sf1));
/*
* simple deletion
*/
assertTrue(store.delete(sf1));
- assertTrue(store.getFeatures().isEmpty());
+ assertTrue(store.getPositionalFeatures().isEmpty());
/*
* non-positional feature deletion
*/
SequenceFeature sf2 = addFeature(store, 0, 0);
- assertTrue(store.getFeatures().contains(sf2));
+ assertFalse(store.getPositionalFeatures().contains(sf2));
+ assertTrue(store.getNonPositionalFeatures().contains(sf2));
assertTrue(store.delete(sf2));
- assertTrue(store.getFeatures().isEmpty());
+ assertTrue(store.getNonPositionalFeatures().isEmpty());
/*
* contact feature deletion
SequenceFeature sf3 = new SequenceFeature("", "Disulphide Bond", 11,
23, Float.NaN, null);
store.addFeature(sf3);
- assertEquals(store.getFeatures().size(), 1);
- assertTrue(store.getFeatures().contains(sf3));
+ assertEquals(store.getPositionalFeatures().size(), 1);
+ assertTrue(store.getPositionalFeatures().contains(sf3));
assertTrue(store.delete(sf3));
- assertTrue(store.getFeatures().isEmpty());
+ assertTrue(store.getPositionalFeatures().isEmpty());
/*
* nested feature deletion
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
- assertEquals(store.getFeatures().size(), 6);
+ 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.getFeatures().size(), 5);
- assertFalse(store.getFeatures().contains(sf6));
+ assertEquals(store.getPositionalFeatures().size(), 5);
+ assertFalse(store.getPositionalFeatures().contains(sf6));
// delete a node with no children
assertTrue(store.delete(sf7));
- assertEquals(store.getFeatures().size(), 4);
- assertFalse(store.getFeatures().contains(sf7));
+ assertEquals(store.getPositionalFeatures().size(), 4);
+ assertFalse(store.getPositionalFeatures().contains(sf7));
// delete root of NCList
assertTrue(store.delete(sf5));
- assertEquals(store.getFeatures().size(), 3);
- assertFalse(store.getFeatures().contains(sf5));
+ assertEquals(store.getPositionalFeatures().size(), 3);
+ assertFalse(store.getPositionalFeatures().contains(sf5));
// continue the killing fields
assertTrue(store.delete(sf4));
- assertEquals(store.getFeatures().size(), 2);
- assertFalse(store.getFeatures().contains(sf4));
+ assertEquals(store.getPositionalFeatures().size(), 2);
+ assertFalse(store.getPositionalFeatures().contains(sf4));
assertTrue(store.delete(sf9));
- assertEquals(store.getFeatures().size(), 1);
- assertFalse(store.getFeatures().contains(sf9));
+ assertEquals(store.getPositionalFeatures().size(), 1);
+ assertFalse(store.getPositionalFeatures().contains(sf9));
assertTrue(store.delete(sf8));
- assertTrue(store.getFeatures().isEmpty());
+ assertTrue(store.getPositionalFeatures().isEmpty());
}
@Test(groups = "Functional")
public void testAddFeature()
{
- FeatureStore fs = new FeatureStore();
+ FeatureStore fs = newFeatureStore();
SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
Float.NaN, null);
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 = new FeatureStore();
+ FeatureStore fs = newFeatureStore();
assertTrue(fs.isEmpty());
+ assertEquals(fs.getFeatureCount(true), 0);
/*
* non-nested feature
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
fs.addFeature(sf1);
fs.addFeature(sf2);
fs.addFeature(sf3);
+ assertEquals(fs.getFeatureCount(true), 3);
assertTrue(fs.delete(sf1));
- // FeatureStore should now only contain features in the NCList
- assertEquals(fs.nonNestedFeatures.size(), 0);
- assertEquals(fs.nestedFeatures.size(), 2);
+ assertEquals(fs.getFeatureCount(true), 2);
+ Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) 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 = new FeatureStore();
- assertTrue(fs.getFeatureGroups().isEmpty());
+ 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<String> groups = fs.getFeatureGroups();
+ Set<String> groups = fs.getFeatureGroups(true);
assertEquals(groups.size(), 1);
assertTrue(groups.contains("group1"));
*/
SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1");
fs.addFeature(sf2);
- groups = fs.getFeatureGroups();
+ groups = fs.getFeatureGroups(true);
assertEquals(groups.size(), 1);
assertTrue(groups.contains("group1"));
fs.delete(sf2);
- groups = fs.getFeatureGroups();
+ groups = fs.getFeatureGroups(true);
assertEquals(groups.size(), 1);
assertTrue(groups.contains("group1"));
fs.delete(sf1);
- groups = fs.getFeatureGroups();
- assertTrue(fs.getFeatureGroups().isEmpty());
+ groups = fs.getFeatureGroups(true);
+ assertTrue(fs.getFeatureGroups(true).isEmpty());
SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2");
fs.addFeature(sf3);
fs.addFeature(sf4);
SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null);
fs.addFeature(sf5);
- groups = fs.getFeatureGroups();
+ 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();
+ groups = fs.getFeatureGroups(true);
assertEquals(groups.size(), 2);
assertFalse(groups.contains("group2"));
fs.delete(sf4);
- groups = fs.getFeatureGroups();
+ groups = fs.getFeatureGroups(true);
assertEquals(groups.size(), 1);
assertFalse(groups.contains("Group2"));
fs.delete(sf5);
- groups = fs.getFeatureGroups();
+ 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<SequenceFeature> 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<SequenceFeature> 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<SequenceFeature> nonPos = fs.getNonPositionalFeatures();
+ assertEquals(nonPos.size(), 1);
+ assertTrue(nonPos.contains(sf4));
+
+ // positional features are replaced
+ List<SequenceFeature> 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<SequenceFeature> features = store.getPositionalFeatures();
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(sf1));
+ assertTrue(features.contains(sf2));
+ Collection<SequenceFeature> intervalStore = (Collection<SequenceFeature>) 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));
+ }
+
+ @Test(groups = "Functional")
+ public void testFindFeatures_withResultList()
+ {
+ FeatureStore fs = newFeatureStore();
+ SequenceFeature sf1 = addFeature(fs, 10, 50);
+ SequenceFeature sf2 = addFeature(fs, 150, 250);
+
+ List<SequenceFeature> overlaps = new ArrayList<>();
+ List<SequenceFeature> result = fs.findFeatures(200, 200,
+ overlaps);
+ assertSame(result, overlaps);
+ assertEquals(result.size(), 1);
+ assertTrue(result.contains(sf2));
+ assertFalse(result.contains(sf1));
+
+ /*
+ * if no list supplied, method creates one
+ */
+ result = fs.findFeatures(200, 200, null);
+ assertEquals(result.size(), 1);
+ assertTrue(result.contains(sf2));
+ assertFalse(result.contains(sf1));
}
}