JAL-2791 new method to test if feature fails colour threshold test
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 27 Sep 2018 15:39:51 +0000 (16:39 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 27 Sep 2018 15:39:51 +0000 (16:39 +0100)
src/jalview/api/FeatureColourI.java
src/jalview/schemes/FeatureColour.java
test/jalview/schemes/FeatureColourTest.java

index 4dbb1bb..999104c 100644 (file)
@@ -192,4 +192,16 @@ public interface FeatureColourI
    * @return
    */
   void setAttributeName(String... name);
+
+  /**
+   * Answers true if colour has a threshold set, and the feature score (or other
+   * attribute selected for colouring) is outwith the threshold.
+   * <p>
+   * Answers false if not a graduated colour, or no threshold is set, or value
+   * is not outwith the threshold, or value is null or non-numeric.
+   * 
+   * @param sf
+   * @return
+   */
+  boolean isOutwithThreshold(SequenceFeature sf);
 }
index 51e7645..f34478c 100644 (file)
@@ -689,9 +689,12 @@ public class FeatureColour implements FeatureColourI
 
   /**
    * Returns the colour for the given instance of the feature. This may be a
-   * simple colour, a colour generated from the feature description (if
-   * isColourByLabel()), or a colour derived from the feature score (if
-   * isGraduatedColour()).
+   * simple colour, a colour generated from the feature description or other
+   * attribute (if isColourByLabel()), or a colour derived from the feature
+   * score or other attribute (if isGraduatedColour()).
+   * <p>
+   * Answers null if feature score (or attribute) value lies outside a
+   * configured threshold.
    * 
    * @param feature
    * @return
@@ -890,4 +893,32 @@ public class FeatureColour implements FeatureColourI
     attributeName = name;
   }
 
+  @Override
+  public boolean isOutwithThreshold(SequenceFeature feature)
+  {
+    if (!isGraduatedColour())
+    {
+      return false;
+    }
+    float scr = feature.getScore();
+    if (attributeName != null)
+    {
+      try
+      {
+        String attVal = feature.getValueAsString(attributeName);
+        scr = Float.valueOf(attVal);
+      } catch (Throwable e)
+      {
+        scr = Float.NaN;
+      }
+    }
+    if (Float.isNaN(scr))
+    {
+      return false;
+    }
+
+    return ((isAboveThreshold() && scr <= threshold)
+            || (isBelowThreshold() && scr >= threshold));
+  }
+
 }
index a96caec..6ccce85 100644 (file)
@@ -712,4 +712,44 @@ public class FeatureColourTest
     Color expected = new Color(70, 120, 170);
     assertEquals(expected, fc.getColor(sf));
   }
+
+  @Test(groups = { "Functional" })
+  public void testIsOutwithThreshold()
+  {
+    FeatureColourI fc = new FeatureColour(Color.red);
+    SequenceFeature sf = new SequenceFeature("METAL", "desc", 10, 12, 1.2f, "grp");
+    assertFalse(fc.isOutwithThreshold(null));
+    assertFalse(fc.isOutwithThreshold(sf));
+
+    fc = new FeatureColour(Color.white, Color.black, Color.green, 0f, 10f);
+    assertFalse(fc.isOutwithThreshold(sf)); // no threshold
+
+    fc.setAboveThreshold(true);
+    fc.setThreshold(1f);
+    assertFalse(fc.isOutwithThreshold(sf)); // feature score 1.2 is above 1
+
+    fc.setThreshold(2f);
+    assertTrue(fc.isOutwithThreshold(sf)); // feature score 1.2 is not above 2
+
+    fc.setBelowThreshold(true);
+    assertFalse(fc.isOutwithThreshold(sf)); // feature score 1.2 is below 2
+
+    fc.setThreshold(1f);
+    assertTrue(fc.isOutwithThreshold(sf)); // feature score 1.2 is not below 1
+
+    /*
+     * with attribute value threshold
+     */
+    fc.setAttributeName("AC");
+    assertFalse(fc.isOutwithThreshold(sf)); // missing attribute AC is ignored
+
+    sf.setValue("AC", "-1");
+    assertFalse(fc.isOutwithThreshold(sf)); // value -1 is below 1
+
+    sf.setValue("AC", "1");
+    assertTrue(fc.isOutwithThreshold(sf)); // value 1 is not below 1
+
+    sf.setValue("AC", "junk");
+    assertFalse(fc.isOutwithThreshold(sf)); // bad value is ignored
+  }
 }