JAL-2630 first pass groovy colour scheme (with slight refactoring)
[jalview.git] / src / jalview / schemes / ResidueColourScheme.java
index c1eeafa..7dbcced 100755 (executable)
@@ -29,7 +29,6 @@ import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceI;
 import jalview.util.ColorUtils;
 import jalview.util.Comparison;
-import jalview.util.MessageManager;
 
 import java.awt.Color;
 import java.util.Map;
@@ -37,14 +36,23 @@ import java.util.Map;
 /**
  * Base class for residue-based colour schemes
  */
-public class ResidueColourScheme implements ColourSchemeI
+public abstract class ResidueColourScheme implements ColourSchemeI
 {
   public static final String NONE = "None";
 
+  public static final String USER_DEFINED = "User Defined";
+
+  /*
+   * lookup up by character value e.g. 'G' to the colors array index
+   * e.g. if symbolIndex['K'] = 11 then colors[11] is the colour for K
+   */
   final int[] symbolIndex;
 
   boolean conservationColouring = false;
 
+  /*
+   * colour for residue characters as indexed by symbolIndex
+   */
   Color[] colors = null;
 
   int threshold = 0;
@@ -110,6 +118,7 @@ public class ResidueColourScheme implements ColourSchemeI
   @Override
   public Color findColour()
   {
+    // TODO delete this method in favour of ColorUtils.parseColourString()?
     return findColour('A');
   }
 
@@ -125,24 +134,46 @@ public class ResidueColourScheme implements ColourSchemeI
   @Override
   public Color findColour(char c, int j, SequenceI seq)
   {
-    Color currentColour;
+    Color colour = Color.white;
 
-    if (colors != null && symbolIndex != null && (threshold == 0)
-            || aboveThreshold(c, j))
+    if (colors != null && symbolIndex != null)
     {
-      currentColour = colors[symbolIndex[c]];
+      colour = colors[symbolIndex[c]];
     }
-    else
+    colour = adjustColour(c, j, colour);
+
+    return colour;
+  }
+
+  /**
+   * Adjusts colour by applying thresholding or conservation shading, if in
+   * force. That is
+   * <ul>
+   * <li>if there is a threshold set for colouring, and the residue doesn't
+   * match the consensus (or a joint consensus) residue, or the consensus score
+   * is not above the threshold, then the colour is set to white</li>
+   * <li>if conservation colouring is selected, the colour is faded by an amount
+   * depending on the conservation score for the column, and the conservation
+   * colour threshold</li>
+   * </ul>
+   * 
+   * @param symbol
+   * @param column
+   * @param colour
+   * @return
+   */
+  protected Color adjustColour(char symbol, int column, Color colour)
+  {
+    if (!aboveThreshold(symbol, column))
     {
-      currentColour = Color.white;
+      colour = Color.white;
     }
 
     if (conservationColouring)
     {
-      currentColour = applyConservation(currentColour, j);
+      colour = applyConservation(colour, column);
     }
-
-    return currentColour;
+    return colour;
   }
 
   /**
@@ -186,6 +217,10 @@ public class ResidueColourScheme implements ColourSchemeI
    */
   public boolean aboveThreshold(char residue, int column)
   {
+    if (threshold == 0)
+    {
+      return true;
+    }
     if ('a' <= residue && residue <= 'z')
     {
       // TO UPPERCASE !!!
@@ -339,24 +374,9 @@ public class ResidueColourScheme implements ColourSchemeI
   {
   }
 
-  @Override
-  public ColourSchemeI applyTo(AnnotatedCollectionI sg,
-          Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
-  {
-    try
-    {
-      return getClass().newInstance();
-    } catch (Exception q)
-    {
-      throw new Error(MessageManager.formatMessage(
-              "error.implementation_error_cannot_duplicate_colour_scheme",
-              new String[] { getClass().getName() }), q);
-    }
-  }
-
   /**
    * Answers false if the colour scheme is nucleotide or peptide specific, and
-   * the data does not match, else false. Override to modify or extend this test
+   * the data does not match, else true. Override to modify or extend this test
    * as required.
    */
   @Override
@@ -368,12 +388,16 @@ public class ResidueColourScheme implements ColourSchemeI
     }
 
     /*
-     * inspect the data context (alignment dataset) for residue type
+     * inspect the data context (alignment) for residue type
      */
     boolean nucleotide = false;
-    AnnotatedCollectionI context = ac.getContext();
-    if (context != null)
+    if (ac instanceof AlignmentI)
+    {
+      nucleotide = ((AlignmentI) ac).isNucleotide();
+    }
+    else
     {
+      AnnotatedCollectionI context = ac.getContext();
       if (context instanceof AlignmentI)
       {
         nucleotide = ((AlignmentI) context).isNucleotide();
@@ -384,14 +408,6 @@ public class ResidueColourScheme implements ColourSchemeI
         return true;
       }
     }
-    else if (ac instanceof AlignmentI)
-    {
-      nucleotide = ((AlignmentI) ac).isNucleotide();
-    }
-    else
-    {
-      return true;
-    }
 
     /*
      * does data type match colour scheme type?
@@ -420,9 +436,13 @@ public class ResidueColourScheme implements ColourSchemeI
     return false;
   }
 
+  /**
+   * Default method returns true. Override this to return false in colour
+   * schemes that are not determined solely by the sequence symbol.
+   */
   @Override
-  public String getSchemeName()
+  public boolean isSimple()
   {
-    return "Residue";
+    return true;
   }
 }