JAL-2876 some Checkstyle and other review comments addressed
[jalview.git] / src / jalview / schemes / FeatureColour.java
index dbe4901..2007f8b 100644 (file)
@@ -33,13 +33,23 @@ import java.util.StringTokenizer;
  */
 public class FeatureColour implements FeatureColourI
 {
-  private static final String BAR = "|";
+  private static final float _255F = 255f;
 
-  final private Color colour;
+  private static final String ABOVE = "above";
 
-  final private Color minColour;
+  private static final String BELOW = "below";
 
-  final private Color maxColour;
+  private static final String ABSO = "abso";
+
+  private static final String LABEL = "label";
+
+  private static final String PIPE = "|";
+
+  private final Color colour;
+
+  private final Color minColour;
+
+  private final Color maxColour;
 
   private boolean graduatedColour;
 
@@ -61,17 +71,118 @@ public class FeatureColour implements FeatureColourI
 
   private boolean autoScaled;
 
-  final private float minRed;
+  private final float minRed;
+
+  private final float minGreen;
 
-  final private float minGreen;
+  private final float minBlue;
 
-  final private float minBlue;
+  private final float deltaRed;
 
-  final private float deltaRed;
+  private final float deltaGreen;
 
-  final private float deltaGreen;
+  private final float deltaBlue;
+
+  /**
+   * Default constructor
+   */
+  public FeatureColour()
+  {
+    this((Color) null);
+  }
 
-  final private float deltaBlue;
+  /**
+   * Constructor given a simple colour
+   * 
+   * @param c
+   */
+  public FeatureColour(Color c)
+  {
+    minColour = Color.WHITE;
+    maxColour = Color.BLACK;
+    minRed = 0f;
+    minGreen = 0f;
+    minBlue = 0f;
+    deltaRed = 0f;
+    deltaGreen = 0f;
+    deltaBlue = 0f;
+    colour = c;
+  }
+
+  /**
+   * Constructor given a colour range and a score range
+   * 
+   * @param low
+   * @param high
+   * @param min
+   * @param max
+   */
+  public FeatureColour(Color low, Color high, float min, float max)
+  {
+    graduatedColour = true;
+    colour = null;
+    minColour = low == null ? Color.WHITE : low;
+    maxColour = high == null ? Color.BLACK : high;
+    threshold = Float.NaN;
+    isHighToLow = min >= max;
+    minRed = minColour.getRed() / _255F;
+    minGreen = minColour.getGreen() / _255F;
+    minBlue = minColour.getBlue() / _255F;
+    deltaRed = (maxColour.getRed() / _255F) - minRed;
+    deltaGreen = (maxColour.getGreen() / _255F) - minGreen;
+    deltaBlue = (maxColour.getBlue() / _255F) - minBlue;
+    if (isHighToLow)
+    {
+      base = max;
+      range = min - max;
+    }
+    else
+    {
+      base = min;
+      range = max - min;
+    }
+  }
+
+  /**
+   * Copy constructor
+   * 
+   * @param fc
+   */
+  public FeatureColour(FeatureColour fc)
+  {
+    graduatedColour = fc.graduatedColour;
+    colour = fc.colour;
+    minColour = fc.minColour;
+    maxColour = fc.maxColour;
+    minRed = fc.minRed;
+    minGreen = fc.minGreen;
+    minBlue = fc.minBlue;
+    deltaRed = fc.deltaRed;
+    deltaGreen = fc.deltaGreen;
+    deltaBlue = fc.deltaBlue;
+    base = fc.base;
+    range = fc.range;
+    isHighToLow = fc.isHighToLow;
+    setAboveThreshold(fc.isAboveThreshold());
+    setBelowThreshold(fc.isBelowThreshold());
+    setThreshold(fc.getThreshold());
+    setAutoScaled(fc.isAutoScaled());
+    setColourByLabel(fc.isColourByLabel());
+  }
+
+  /**
+   * Copy constructor with new min/max ranges
+   * 
+   * @param fc
+   * @param min
+   * @param max
+   */
+  public FeatureColour(FeatureColour fc, float min, float max)
+  {
+    this(fc);
+    graduatedColour = true;
+    updateBounds(min, max);
+  }
 
   /**
    * Parses a Jalview features file format colour descriptor
@@ -96,20 +207,20 @@ public class FeatureColour implements FeatureColourI
    */
   public static FeatureColour parseJalviewFeatureColour(String descriptor)
   {
-    StringTokenizer gcol = new StringTokenizer(descriptor, "|", true);
+    StringTokenizer gcol = new StringTokenizer(descriptor, PIPE, true);
     float min = Float.MIN_VALUE;
     float max = Float.MAX_VALUE;
     boolean labelColour = false;
 
     String mincol = gcol.nextToken();
-    if (mincol == "|")
+    if (mincol == PIPE)
     {
       throw new IllegalArgumentException(
               "Expected either 'label' or a colour specification in the line: "
                       + descriptor);
     }
     String maxcol = null;
-    if (mincol.toLowerCase().indexOf("label") == 0)
+    if (mincol.toLowerCase().indexOf(LABEL) == 0)
     {
       labelColour = true;
       mincol = (gcol.hasMoreTokens() ? gcol.nextToken() : null);
@@ -125,8 +236,8 @@ public class FeatureColour implements FeatureColourI
       Color colour = ColorUtils.parseColourString(descriptor);
       if (colour == null)
       {
-        throw new IllegalArgumentException("Invalid colour descriptor: "
-                + descriptor);
+        throw new IllegalArgumentException(
+                "Invalid colour descriptor: " + descriptor);
       }
       return new FeatureColour(colour);
     }
@@ -136,11 +247,13 @@ public class FeatureColour implements FeatureColourI
      * autoScaled == false ('abso'): colours range over min/max range
      */
     boolean autoScaled = true;
-    String tok = null, minval, maxval;
+    String tok = null;
+    String minval;
+    String maxval;
     if (mincol != null)
     {
       // at least four more tokens
-      if (mincol.equals("|"))
+      if (mincol.equals(PIPE))
       {
         mincol = "";
       }
@@ -149,7 +262,7 @@ public class FeatureColour implements FeatureColourI
         gcol.nextToken(); // skip next '|'
       }
       maxcol = gcol.nextToken();
-      if (maxcol.equals("|"))
+      if (maxcol.equals(PIPE))
       {
         maxcol = "";
       }
@@ -159,7 +272,7 @@ public class FeatureColour implements FeatureColourI
       }
       tok = gcol.nextToken();
       gcol.nextToken(); // skip next '|'
-      if (tok.toLowerCase().startsWith("abso"))
+      if (tok.toLowerCase().startsWith(ABSO))
       {
         minval = gcol.nextToken();
         gcol.nextToken(); // skip next '|'
@@ -180,7 +293,7 @@ public class FeatureColour implements FeatureColourI
         {
           min = new Float(minval).floatValue();
         }
-      } catch (Exception e)
+      } catch (NumberFormatException e)
       {
         throw new IllegalArgumentException(
                 "Couldn't parse the minimum value for graduated colour ("
@@ -192,7 +305,7 @@ public class FeatureColour implements FeatureColourI
         {
           max = new Float(maxval).floatValue();
         }
-      } catch (Exception e)
+      } catch (NumberFormatException e)
       {
         throw new IllegalArgumentException(
                 "Couldn't parse the maximum value for graduated colour ("
@@ -219,16 +332,17 @@ public class FeatureColour implements FeatureColourI
       featureColour.setColourByLabel(labelColour);
       featureColour.setAutoScaled(autoScaled);
       // add in any additional parameters
-      String ttype = null, tval = null;
+      String ttype = null;
+      String tval = null;
       if (gcol.hasMoreTokens())
       {
         // threshold type and possibly a threshold value
         ttype = gcol.nextToken();
-        if (ttype.toLowerCase().startsWith("below"))
+        if (ttype.toLowerCase().startsWith(BELOW))
         {
           featureColour.setBelowThreshold(true);
         }
-        else if (ttype.toLowerCase().startsWith("above"))
+        else if (ttype.toLowerCase().startsWith(ABOVE))
         {
           featureColour.setAboveThreshold(true);
         }
@@ -236,8 +350,8 @@ public class FeatureColour implements FeatureColourI
         {
           if (!ttype.toLowerCase().startsWith("no"))
           {
-            System.err.println("Ignoring unrecognised threshold type : "
-                    + ttype);
+            System.err.println(
+                    "Ignoring unrecognised threshold type : " + ttype);
           }
         }
       }
@@ -248,7 +362,7 @@ public class FeatureColour implements FeatureColourI
           gcol.nextToken();
           tval = gcol.nextToken();
           featureColour.setThreshold(new Float(tval).floatValue());
-        } catch (Exception e)
+        } catch (NumberFormatException e)
         {
           System.err.println("Couldn't parse threshold value as a float: ("
                   + tval + ")");
@@ -256,11 +370,11 @@ public class FeatureColour implements FeatureColourI
       }
       if (gcol.hasMoreTokens())
       {
-        System.err
-                .println("Ignoring additional tokens in parameters in graduated colour specification\n");
+        System.err.println(
+                "Ignoring additional tokens in parameters in graduated colour specification\n");
         while (gcol.hasMoreTokens())
         {
-          System.err.println("|" + gcol.nextToken());
+          System.err.println(PIPE + gcol.nextToken());
         }
         System.err.println("\n");
       }
@@ -271,115 +385,6 @@ public class FeatureColour implements FeatureColourI
     }
   }
 
-  /**
-   * Default constructor
-   */
-  public FeatureColour()
-  {
-    this((Color) null);
-  }
-
-  /**
-   * Constructor given a simple colour
-   * 
-   * @param c
-   */
-  public FeatureColour(Color c)
-  {
-    minColour = Color.WHITE;
-    maxColour = Color.BLACK;
-    minRed = 0f;
-    minGreen = 0f;
-    minBlue = 0f;
-    deltaRed = 0f;
-    deltaGreen = 0f;
-    deltaBlue = 0f;
-    colour = c;
-  }
-
-  /**
-   * Constructor given a colour range and a score range
-   * 
-   * @param low
-   * @param high
-   * @param min
-   * @param max
-   */
-  public FeatureColour(Color low, Color high, float min, float max)
-  {
-    if (low == null)
-    {
-      low = Color.white;
-    }
-    if (high == null)
-    {
-      high = Color.black;
-    }
-    graduatedColour = true;
-    colour = null;
-    minColour = low;
-    maxColour = high;
-    threshold = Float.NaN;
-    isHighToLow = min >= max;
-    minRed = low.getRed() / 255f;
-    minGreen = low.getGreen() / 255f;
-    minBlue = low.getBlue() / 255f;
-    deltaRed = (high.getRed() / 255f) - minRed;
-    deltaGreen = (high.getGreen() / 255f) - minGreen;
-    deltaBlue = (high.getBlue() / 255f) - minBlue;
-    if (isHighToLow)
-    {
-      base = max;
-      range = min - max;
-    }
-    else
-    {
-      base = min;
-      range = max - min;
-    }
-  }
-
-  /**
-   * Copy constructor
-   * 
-   * @param fc
-   */
-  public FeatureColour(FeatureColour fc)
-  {
-    graduatedColour = fc.graduatedColour;
-    colour = fc.colour;
-    minColour = fc.minColour;
-    maxColour = fc.maxColour;
-    minRed = fc.minRed;
-    minGreen = fc.minGreen;
-    minBlue = fc.minBlue;
-    deltaRed = fc.deltaRed;
-    deltaGreen = fc.deltaGreen;
-    deltaBlue = fc.deltaBlue;
-    base = fc.base;
-    range = fc.range;
-    isHighToLow = fc.isHighToLow;
-    setAboveThreshold(fc.isAboveThreshold());
-    setBelowThreshold(fc.isBelowThreshold());
-    setThreshold(fc.getThreshold());
-    setAutoScaled(fc.isAutoScaled());
-    setColourByLabel(fc.isColourByLabel());
-  }
-
-  /**
-   * Copy constructor with new min/max ranges
-   * 
-   * @param fc
-   * @param min
-   * @param max
-   */
-  public FeatureColour(FeatureColour fc, float min, float max)
-  {
-    this(fc);
-    graduatedColour = true;
-    updateBounds(min, max);
-  }
-
   @Override
   public boolean isGraduatedColour()
   {
@@ -529,53 +534,70 @@ 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()).
+   * {@inheritDoc}
    * 
    * @param feature
    * @return
    */
   @Override
-  public Color getColor(SequenceFeature feature)
+  public Color getColour(SequenceFeature feature)
   {
-    if (isColourByLabel())
-    {
-      return ColorUtils
-              .createColourFromName(feature.getDescription());
-    }
-
-    if (!isGraduatedColour())
+    if (isSimpleColour())
     {
       return getColour();
     }
 
-    // todo should we check for above/below threshold here?
-    if (range == 0.0)
+    /*
+     * return null if score is outwith any threshold
+     * (for graduated colour or colour by label)
+     */
+    float scr = feature.getScore();
+    boolean isNan = Float.isNaN(scr);
+    if (!isNan)
     {
-      return getMaxColour();
+      boolean isAbove = isAboveThreshold() && scr <= threshold;
+      boolean isBelow = !isNan && isBelowThreshold() && scr >= threshold;
+      if (isAbove || isBelow)
+      {
+        return null;
+      }
     }
-    float scr = feature.getScore();
-    if (Float.isNaN(scr))
+
+    if (isColourByLabel())
     {
-      return getMinColour();
+      return ColorUtils.createColourFromName(feature.getDescription());
     }
-    float scl = (scr - base) / range;
-    if (isHighToLow)
+
+    Color result = null;
+
+    if (isNan)
     {
-      scl = -scl;
+      result = getMinColour();
     }
-    if (scl < 0f)
+    else if (range == 0.0)
     {
-      scl = 0f;
+      result = getMaxColour();
     }
-    if (scl > 1f)
+    else
     {
-      scl = 1f;
+      float scl = (scr - base) / range;
+      if (isHighToLow)
+      {
+        scl = -scl;
+      }
+      if (scl < 0f)
+      {
+        scl = 0f;
+      }
+      if (scl > 1f)
+      {
+        scl = 1f;
+      }
+      result = new Color(minRed + scl * deltaRed,
+              minGreen + scl * deltaGreen, minBlue + scl * deltaBlue);
     }
-    return new Color(minRed + scl * deltaRed, minGreen + scl * deltaGreen,
-            minBlue + scl * deltaBlue);
+
+    return result;
   }
 
   /**
@@ -602,44 +624,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()
   {
@@ -665,32 +649,32 @@ public class FeatureColour implements FeatureColourI
       StringBuilder sb = new StringBuilder(32);
       if (isColourByLabel())
       {
-        sb.append("label");
+        sb.append(LABEL);
         if (hasThreshold())
         {
-          sb.append(BAR).append(BAR).append(BAR);
+          sb.append(PIPE).append(PIPE).append(PIPE);
         }
       }
       if (isGraduatedColour())
       {
-        sb.append(Format.getHexString(getMinColour())).append(BAR);
-        sb.append(Format.getHexString(getMaxColour())).append(BAR);
+        sb.append(Format.getHexString(getMinColour())).append(PIPE);
+        sb.append(Format.getHexString(getMaxColour())).append(PIPE);
         if (!isAutoScaled())
         {
-          sb.append("abso").append(BAR);
+          sb.append(ABSO).append(PIPE);
         }
       }
       if (hasThreshold() || isGraduatedColour())
       {
-        sb.append(getMin()).append(BAR);
-        sb.append(getMax()).append(BAR);
+        sb.append(getMin()).append(PIPE);
+        sb.append(getMax()).append(PIPE);
         if (isBelowThreshold())
         {
-          sb.append("below").append(BAR).append(getThreshold());
+          sb.append(BELOW).append(PIPE).append(getThreshold());
         }
         else if (isAboveThreshold())
         {
-          sb.append("above").append(BAR).append(getThreshold());
+          sb.append(ABOVE).append(PIPE).append(getThreshold());
         }
         else
         {