Merge branch 'develop' into features/JAL-2446NCList
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Sun, 23 Jul 2017 07:59:37 +0000 (08:59 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Sun, 23 Jul 2017 07:59:37 +0000 (08:59 +0100)
Conflicts:
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java

src/jalview/api/FeatureColourI.java
src/jalview/appletgui/FeatureColourChooser.java
src/jalview/gui/FeatureColourChooser.java
src/jalview/renderer/seqfeatures/FeatureRenderer.java
src/jalview/schemes/FeatureColour.java
src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java
test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java
test/jalview/schemes/FeatureColourTest.java

index 01eb7fa..0ded079 100644 (file)
@@ -146,7 +146,9 @@ public interface FeatureColourI
   boolean hasThreshold();
 
   /**
-   * Returns the computed colour for the given sequence feature
+   * Returns the computed colour for the given sequence feature. Answers null if
+   * the score of this feature instance is outside the range to render (if any),
+   * i.e. lies below or above a configured threshold.
    * 
    * @param feature
    * @return
@@ -154,17 +156,6 @@ public interface FeatureColourI
   Color getColor(SequenceFeature feature);
 
   /**
-   * Answers true if the feature has a simple colour, or is coloured by label,
-   * or has a graduated colour and the score of this feature instance is within
-   * the range to render (if any), i.e. does not lie below or above any
-   * threshold set.
-   * 
-   * @param feature
-   * @return
-   */
-  boolean isColored(SequenceFeature feature);
-
-  /**
    * Update the min-max range for a graduated colour scheme
    * 
    * @param min
index 0e85017..4075e8b 100644 (file)
@@ -95,9 +95,11 @@ public class FeatureColourChooser extends Panel implements ActionListener,
     float mm[] = fr.getMinMax().get(type)[0];
     min = mm[0];
     max = mm[1];
+    threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
     oldcs = fr.getFeatureColours().get(type);
     if (oldcs.isGraduatedColour())
     {
+      threshline.value = oldcs.getThreshold();
       cs = new FeatureColour((FeatureColour) oldcs, min, max);
     }
     else
@@ -384,14 +386,6 @@ public class FeatureColourChooser extends Panel implements ActionListener,
       thresholdValue.setText("");
     }
 
-    else if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD
-            && threshline == null)
-    {
-      // todo visual indication of feature threshold
-      threshline = new jalview.datamodel.GraphLine((max - min) / 2f,
-              "Threshold", Color.black);
-    }
-
     if (aboveThreshold != AnnotationColourGradient.NO_THRESHOLD)
     {
       adjusting = true;
index 5594e1a..a1c1bff 100644 (file)
@@ -178,9 +178,10 @@ public class FeatureColourChooser extends JalviewDialog
       // initialise threshold slider and selector
       threshold.setSelectedIndex(cs.isAboveThreshold() ? 1 : 2);
       slider.setEnabled(true);
+      slider.setValue((int) (cs.getThreshold() * scaleFactor));
       thresholdValue.setEnabled(true);
       threshline = new GraphLine((max - min) / 2f, "Threshold", Color.black);
-
+      threshline.value = cs.getThreshold();
     }
 
     adjusting = false;
index 3f44bcc..d661915 100644 (file)
@@ -309,6 +309,11 @@ public class FeatureRenderer extends FeatureRendererModel
       for (SequenceFeature sf : overlaps)
       {
         Color featureColour = fc.getColor(sf);
+        if (featureColour == null)
+        {
+          // score feature outwith threshold for colouring
+          continue;
+        }
 
         /*
          * if feature starts/ends outside the visible range,
@@ -332,7 +337,11 @@ public class FeatureRenderer extends FeatureRendererModel
         int featureEndCol = sf.begin == sf.end ? featureStartCol : seq
                 .findIndex(visibleEnd);
 
-        if (sf.isContactFeature())
+        // Color featureColour = getColour(sequenceFeature);
+
+        boolean isContactFeature = sf.isContactFeature();
+
+        if (isContactFeature)
         {
           boolean drawn = renderFeature(g, seq, featureStartCol - 1,
                   featureStartCol - 1, featureColour, start, end, y1,
@@ -345,7 +354,7 @@ public class FeatureRenderer extends FeatureRendererModel
             drawnColour = featureColour;
           }
         }
-        else if (showFeature(sf))
+        else
         {
           /*
            * showing feature score by height of colour
@@ -443,7 +452,11 @@ public class FeatureRenderer extends FeatureRendererModel
       {
         if (!featureGroupNotShown(sequenceFeature))
         {
-          return getColour(sequenceFeature);
+          Color col = getColour(sequenceFeature);
+          if (col != null)
+          {
+            return col;
+          }
         }
       }
     }
index dbe4901..ed3e02d 100644 (file)
@@ -551,12 +551,23 @@ public class FeatureColour implements FeatureColourI
       return getColour();
     }
 
-    // todo should we check for above/below threshold here?
+    /*
+     * graduated colour case, optionally with threshold
+     * (treating Float.NaN as within visible range here)
+     */
+    float scr = feature.getScore();
+    if (isAboveThreshold() && scr <= threshold)
+    {
+      return null;
+    }
+    if (isBelowThreshold() && scr >= threshold)
+    {
+      return null;
+    }
     if (range == 0.0)
     {
       return getMaxColour();
     }
-    float scr = feature.getScore();
     if (Float.isNaN(scr))
     {
       return getMinColour();
@@ -602,44 +613,6 @@ public class FeatureColour implements FeatureColourI
     return (isHighToLow) ? (base + range) : base;
   }
 
-  /**
-   * Answers true if the feature has a simple colour, or is coloured by label,
-   * or has a graduated colour and the score of this feature instance is within
-   * the range to render (if any), i.e. does not lie below or above any
-   * threshold set.
-   * 
-   * @param feature
-   * @return
-   */
-  @Override
-  public boolean isColored(SequenceFeature feature)
-  {
-    if (isColourByLabel() || !isGraduatedColour())
-    {
-      return true;
-    }
-
-    float val = feature.getScore();
-    if (Float.isNaN(val))
-    {
-      return true;
-    }
-    if (Float.isNaN(this.threshold))
-    {
-      return true;
-    }
-
-    if (isAboveThreshold() && val <= threshold)
-    {
-      return false;
-    }
-    if (isBelowThreshold() && val >= threshold)
-    {
-      return false;
-    }
-    return true;
-  }
-
   @Override
   public boolean isSimpleColour()
   {
index de1ee5e..1d09dca 100644 (file)
@@ -559,7 +559,8 @@ public abstract class FeatureRendererModel implements
    * Returns the configured colour for a particular feature instance. This
    * includes calculation of 'colour by label', or of a graduated score colour,
    * if applicable. It does not take into account feature visibility or colour
-   * transparency.
+   * transparency. Returns null for a score feature whose score value lies
+   * outside any colour threshold.
    * 
    * @param feature
    * @return
@@ -571,19 +572,6 @@ public abstract class FeatureRendererModel implements
   }
 
   /**
-   * Answers true unless the feature has a graduated colour scheme and the
-   * feature value lies outside the current threshold for display
-   * 
-   * @param sequenceFeature
-   * @return
-   */
-  protected boolean showFeature(SequenceFeature sequenceFeature)
-  {
-    FeatureColourI fc = getFeatureStyle(sequenceFeature.type);
-    return fc.isColored(sequenceFeature);
-  }
-
-  /**
    * Answers true if the feature type is currently selected to be displayed,
    * else false
    * 
index 28d608f..ecabfca 100644 (file)
@@ -448,4 +448,69 @@ public class FeatureColourFinderTest
     FeatureColourFinder finder2 = new FeatureColourFinder(null);
     assertTrue(finder2.noFeaturesDisplayed());
   }
+
+  @Test(groups = "Functional")
+  public void testFindFeatureColour_graduatedWithThreshold()
+  {
+    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
+            2, 0f, "KdGroup"));
+    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 4,
+            4, 5f, "KdGroup"));
+    seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 7,
+            7, 10f, "KdGroup"));
+  
+    /*
+     * graduated colour from 0 to 10
+     * above threshold value of 5
+     */
+    Color min = new Color(100, 50, 150);
+    Color max = new Color(200, 0, 100);
+    FeatureColourI fc = new FeatureColour(min, max, 0, 10);
+    fc.setAboveThreshold(true);
+    fc.setThreshold(5f);
+    fr.setColour("kd", fc);
+    fr.featuresAdded();
+    av.setShowSequenceFeatures(true);
+  
+    /*
+     * position 2, column 1, score 0 - below threshold - default colour
+     */
+    Color c = finder.findFeatureColour(Color.blue, seq, 1);
+    assertEquals(c, Color.blue);
+
+    /*
+     * position 4, column 3, score 5 - at threshold - default colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 3);
+    assertEquals(c, Color.blue);
+  
+    /*
+     * position 7, column 9, score 10 - maximum colour in range
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 9);
+    assertEquals(c, max);
+
+    /*
+     * now colour below threshold of 5
+     */
+    fc.setBelowThreshold(true);
+
+    /*
+     * position 2, column 1, score 0 - min colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 1);
+    assertEquals(c, min);
+
+    /*
+     * position 4, column 3, score 5 - at threshold - default colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 3);
+    assertEquals(c, Color.blue);
+
+    /*
+     * position 7, column 9, score 10 - above threshold - default colour
+     */
+    c = finder.findFeatureColour(Color.blue, seq, 9);
+    assertEquals(c, Color.blue);
+  }
 }
index 1beca80..03f7efa 100644 (file)
@@ -22,6 +22,7 @@ package jalview.schemes;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.AssertJUnit.fail;
 
@@ -84,62 +85,6 @@ public class FeatureColourTest
   }
 
   @Test(groups = { "Functional" })
-  public void testIsColored_simpleColour()
-  {
-    FeatureColour fc = new FeatureColour(Color.RED);
-    assertTrue(fc
-            .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
-  }
-
-  @Test(groups = { "Functional" })
-  public void testIsColored_colourByLabel()
-  {
-    FeatureColour fc = new FeatureColour();
-    fc.setColourByLabel(true);
-    assertTrue(fc
-            .isColored(new SequenceFeature("Cath", "", 1, 2, 0f, null)));
-  }
-
-  @Test(groups = { "Functional" })
-  public void testIsColored_aboveThreshold()
-  {
-    // graduated colour range from score 20 to 100
-    FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 20f,
-            100f);
-
-    // score 0 is adjusted to bottom of range
-    SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 0f,
-            null);
-    assertTrue(fc.isColored(sf));
-    assertEquals(Color.WHITE, fc.getColor(sf));
-
-    // score 120 is adjusted to top of range
-    sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
-            sf.getFeatureGroup(), 120f);
-    assertEquals(Color.BLACK, fc.getColor(sf));
-
-    // value below threshold is still rendered
-    // setting threshold has no effect yet...
-    fc.setThreshold(60f);
-    sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
-            sf.getFeatureGroup(), 36f);
-    assertTrue(fc.isColored(sf));
-    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
-    // now apply threshold:
-    fc.setAboveThreshold(true);
-    assertFalse(fc.isColored(sf));
-    // colour is still returned though ?!?
-    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
-
-    sf = new SequenceFeature(sf, sf.getBegin(), sf.getEnd(),
-            sf.getFeatureGroup(), 84f);
-    // above threshold now
-    assertTrue(fc.isColored(sf));
-    assertEquals(new Color(51, 51, 51), fc.getColor(sf));
-  }
-
-  @Test(groups = { "Functional" })
   public void testGetColor_simpleColour()
   {
     FeatureColour fc = new FeatureColour(Color.RED);
@@ -176,7 +121,7 @@ public class FeatureColourTest
   }
 
   @Test(groups = { "Functional" })
-  public void testGetColor_belowThreshold()
+  public void testGetColor_aboveBelowThreshold()
   {
     // gradient from [50, 150] from WHITE(255, 255, 255) to BLACK(0, 0, 0)
     FeatureColour fc = new FeatureColour(Color.WHITE, Color.BLACK, 50f,
@@ -184,12 +129,16 @@ public class FeatureColourTest
     SequenceFeature sf = new SequenceFeature("type", "desc", 0, 20, 70f,
             null);
     fc.setThreshold(100f); // ignore for now
-    assertTrue(fc.isColored(sf));
     assertEquals(new Color(204, 204, 204), fc.getColor(sf));
 
     fc.setAboveThreshold(true); // feature lies below threshold
-    assertFalse(fc.isColored(sf));
-    assertEquals(new Color(204, 204, 204), fc.getColor(sf));
+    assertNull(fc.getColor(sf));
+
+    fc.setBelowThreshold(true);
+    fc.setThreshold(70f);
+    assertNull(fc.getColor(sf)); // feature score == threshold - hidden
+    fc.setThreshold(69f);
+    assertNull(fc.getColor(sf)); // feature score > threshold - hidden
   }
 
   /**