JAL-2480 cache min-max score values per sequence and feature type
[jalview.git] / test / jalview / datamodel / features / SequenceFeaturesTest.java
index 84a07b4..eaf20b0 100644 (file)
@@ -16,7 +16,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testGetPositionalFeatures()
   {
-    SequenceFeatures store = new SequenceFeatures();
+    SequenceFeaturesI store = new SequenceFeatures();
     SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
             Float.NaN, null);
     store.add(sf1);
@@ -96,7 +96,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testGetContactFeatures()
   {
-    SequenceFeatures store = new SequenceFeatures();
+    SequenceFeaturesI store = new SequenceFeatures();
     // non-contact
     SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
             Float.NaN, null);
@@ -148,7 +148,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testGetNonPositionalFeatures()
   {
-    SequenceFeatures store = new SequenceFeatures();
+    SequenceFeaturesI store = new SequenceFeatures();
     // positional
     SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
             Float.NaN, null);
@@ -211,7 +211,7 @@ public class SequenceFeaturesTest
    * @param to
    * @return
    */
-  SequenceFeature addFeature(SequenceFeatures sf, String type, int from,
+  SequenceFeature addFeature(SequenceFeaturesI sf, String type, int from,
           int to)
   {
     SequenceFeature sf1 = new SequenceFeature(type, "", from, to,
@@ -224,7 +224,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testFindFeatures()
   {
-    SequenceFeatures sf = new SequenceFeatures();
+    SequenceFeaturesI sf = new SequenceFeatures();
     SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
     SequenceFeature sf2 = addFeature(sf, "Pfam", 1, 15);
     SequenceFeature sf3 = addFeature(sf, "Pfam", 20, 30);
@@ -288,7 +288,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testDelete()
   {
-    SequenceFeatures sf = new SequenceFeatures();
+    SequenceFeaturesI sf = new SequenceFeatures();
     SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
     assertTrue(sf.getPositionalFeatures().contains(sf1));
 
@@ -302,7 +302,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testHasFeatures()
   {
-    SequenceFeatures sf = new SequenceFeatures();
+    SequenceFeaturesI sf = new SequenceFeatures();
     assertFalse(sf.hasFeatures());
 
     SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
@@ -319,7 +319,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testGetFeatureGroups()
   {
-    SequenceFeatures sf = new SequenceFeatures();
+    SequenceFeaturesI sf = new SequenceFeatures();
     assertTrue(sf.getFeatureGroups(true).isEmpty());
     assertTrue(sf.getFeatureGroups(false).isEmpty());
 
@@ -412,7 +412,7 @@ public class SequenceFeaturesTest
   @Test(groups = "Functional")
   public void testGetFeatureTypesForGroups()
   {
-    SequenceFeatures sf = new SequenceFeatures();
+    SequenceFeaturesI sf = new SequenceFeatures();
     assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
   
     /*
@@ -493,4 +493,341 @@ public class SequenceFeaturesTest
     assertTrue(groups.contains("turn"));
     assertTrue(groups.contains("strand"));
   }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureTypes()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    Set<String> types = store.getFeatureTypes();
+    assertTrue(types.isEmpty());
+
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 1);
+    assertTrue(types.contains("Metal"));
+
+    // null type is possible...
+    SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf2);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 2);
+    assertTrue(types.contains(null));
+    assertTrue(types.contains("Metal"));
+
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 3);
+    assertTrue(types.contains("Pfam"));
+
+    /*
+     * add contact feature
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 4);
+    assertTrue(types.contains("Disulphide Bond"));
+
+    /*
+     * add another Pfam
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 4); // unchanged
+
+    /*
+     * delete first Pfam - still have one
+     */
+    assertTrue(store.delete(sf3));
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 4);
+    assertTrue(types.contains("Pfam"));
+
+    /*
+     * delete second Pfam - no longer have one
+     */
+    assertTrue(store.delete(sf5));
+    types = store.getFeatureTypes();
+    assertEquals(types.size(), 3);
+    assertFalse(types.contains("Pfam"));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetFeatureCount()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    assertEquals(store.getFeatureCount(true), 0);
+    assertEquals(store.getFeatureCount(false), 0);
+  
+    /*
+     * add positional
+     */
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    assertEquals(store.getFeatureCount(true), 1);
+    assertEquals(store.getFeatureCount(false), 0);
+
+    /*
+     * another positional
+     */
+    SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf2);
+    assertEquals(store.getFeatureCount(true), 2);
+    assertEquals(store.getFeatureCount(false), 0);
+  
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    assertEquals(store.getFeatureCount(true), 2);
+    assertEquals(store.getFeatureCount(false), 1);
+  
+    /*
+     * add contact feature (counts as 1)
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    assertEquals(store.getFeatureCount(true), 3);
+    assertEquals(store.getFeatureCount(false), 1);
+  
+    /*
+     * add another Pfam
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    assertEquals(store.getFeatureCount(true), 4);
+    assertEquals(store.getFeatureCount(false), 1);
+    assertEquals(store.getFeatureCount(true, "Pfam"), 1);
+    assertEquals(store.getFeatureCount(false, "Pfam"), 1);
+    // search for type==null
+    assertEquals(store.getFeatureCount(true, (String) null), 1);
+    // search with no type specified
+    assertEquals(store.getFeatureCount(true, (String[]) null), 4);
+    assertEquals(store.getFeatureCount(true, "Metal", "Cath"), 1);
+    assertEquals(store.getFeatureCount(true, "Disulphide Bond"), 1);
+    assertEquals(store.getFeatureCount(true, "Metal", "Pfam", null), 3);
+
+    /*
+     * delete first Pfam (non-positional)
+     */
+    assertTrue(store.delete(sf3));
+    assertEquals(store.getFeatureCount(true), 4);
+    assertEquals(store.getFeatureCount(false), 0);
+  
+    /*
+     * delete second Pfam (positional)
+     */
+    assertTrue(store.delete(sf5));
+    assertEquals(store.getFeatureCount(true), 3);
+    assertEquals(store.getFeatureCount(false), 0);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetAllFeatures()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    List<SequenceFeature> features = store.getAllFeatures();
+    assertTrue(features.isEmpty());
+  
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf1);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 1);
+    assertTrue(features.contains(sf1));
+  
+    SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf2);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 2);
+    assertTrue(features.contains(sf2));
+  
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf3));
+  
+    /*
+     * add contact feature
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 4);
+    assertTrue(features.contains(sf4));
+  
+    /*
+     * add another Pfam
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 5);
+    assertTrue(features.contains(sf5));
+    features = store.getAllFeatures("Cath");
+    assertTrue(features.isEmpty());
+    features = store.getAllFeatures("Pfam", "Cath", "Metal");
+    assertEquals(features.size(), 3);
+    assertTrue(features.contains(sf1));
+    assertTrue(features.contains(sf3));
+    assertTrue(features.contains(sf5));
+  
+    /*
+     * delete first Pfam
+     */
+    assertTrue(store.delete(sf3));
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 4);
+    assertFalse(features.contains(sf3));
+  
+    /*
+     * delete second Pfam
+     */
+    assertTrue(store.delete(sf5));
+    features = store.getAllFeatures();
+    assertEquals(features.size(), 3);
+    assertFalse(features.contains(sf3));
+  }
+
+  @Test(groups = "Functional")
+  public void testGetTotalFeatureLength()
+  {
+    SequenceFeaturesI store = new SequenceFeatures();
+    assertEquals(store.getTotalFeatureLength(), 0);
+
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+            Float.NaN, null);
+    assertTrue(store.add(sf1));
+    assertEquals(store.getTotalFeatureLength(), 11);
+
+    // re-add does nothing!
+    assertFalse(store.add(sf1));
+    assertEquals(store.getTotalFeatureLength(), 11);
+
+    /*
+     * add non-positional feature
+     */
+    SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+            Float.NaN, null);
+    store.add(sf3);
+    assertEquals(store.getTotalFeatureLength(), 11);
+
+    /*
+     * add contact feature - counts 1 to feature length
+     */
+    SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+            10, 20, Float.NaN, null);
+    store.add(sf4);
+    assertEquals(store.getTotalFeatureLength(), 12);
+
+    /*
+     * add another Pfam
+     */
+    SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+            Float.NaN, null);
+    store.add(sf5);
+    assertEquals(store.getTotalFeatureLength(), 23);
+
+    /*
+     * delete features
+     */
+    assertTrue(store.delete(sf3)); // non-positional
+    assertEquals(store.getTotalFeatureLength(), 23); // no change
+
+    assertTrue(store.delete(sf5));
+    assertEquals(store.getTotalFeatureLength(), 12);
+
+    assertTrue(store.delete(sf4)); // contact
+    assertEquals(store.getTotalFeatureLength(), 11);
+
+    assertTrue(store.delete(sf1));
+    assertEquals(store.getTotalFeatureLength(), 0);
+  }
+
+  @Test
+  public void testGetMinimumScore_getMaximumScore()
+  {
+    SequenceFeatures sf = new SequenceFeatures();
+    SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 0, 0,
+            Float.NaN, "group"); // non-positional, no score
+    sf.add(sf1);
+    SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 10, 20,
+            Float.NaN, "group"); // positional, no score
+    sf.add(sf2);
+    SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 10, 20, 1f,
+            "group");
+    sf.add(sf3);
+    SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 12, 16, 4f,
+            "group");
+    sf.add(sf4);
+    SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 0, 0, 11f,
+            "group");
+    sf.add(sf5);
+    SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, -7f,
+            "group");
+    sf.add(sf6);
+
+    assertEquals(sf.getMinimumScore("nosuchtype", true), Float.NaN);
+    assertEquals(sf.getMinimumScore("nosuchtype", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("nosuchtype", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("nosuchtype", false), Float.NaN);
+
+    // positional features min-max:
+    assertEquals(sf.getMinimumScore("Metal", true), 1f);
+    assertEquals(sf.getMaximumScore("Metal", true), 4f);
+    assertEquals(sf.getMinimumScore("Cath", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("Cath", true), Float.NaN);
+
+    // non-positional features min-max:
+    assertEquals(sf.getMinimumScore("Cath", false), -7f);
+    assertEquals(sf.getMaximumScore("Cath", false), 11f);
+    assertEquals(sf.getMinimumScore("Metal", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("Metal", false), Float.NaN);
+
+    // delete features; min-max should get recomputed
+    sf.delete(sf6);
+    assertEquals(sf.getMinimumScore("Cath", false), 11f);
+    assertEquals(sf.getMaximumScore("Cath", false), 11f);
+    sf.delete(sf4);
+    assertEquals(sf.getMinimumScore("Metal", true), 1f);
+    assertEquals(sf.getMaximumScore("Metal", true), 1f);
+    sf.delete(sf5);
+    assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
+    sf.delete(sf3);
+    assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
+    sf.delete(sf1);
+    sf.delete(sf2);
+    assertFalse(sf.hasFeatures());
+    assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
+    assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
+    assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
+    assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
+  }
 }