JAL-2938 extracted base class for Hmmer colour schems
[jalview.git] / src / jalview / schemes / HmmerColourScheme.java
similarity index 62%
rename from src/jalview/schemes/HMMERColourScheme.java
rename to src/jalview/schemes/HmmerColourScheme.java
index ee6c873..011c071 100644 (file)
@@ -11,7 +11,8 @@ import java.awt.Color;
 import java.util.Map;
 
 /**
- * A colour scheme based on a selected Hidden Markov Model. The colour is
+ * Base class for colour schemes based on a selected Hidden Markov Model. The
+ * colour is
  * <ul>
  * <li>white for a gap</li>
  * <li>red for an insertion</li>
@@ -21,33 +22,29 @@ import java.util.Map;
  * where information content is the log ratio
  * 
  * <pre>
- *   log(profile match emission probability / residue background probability>
+ *   log(profile match emission probability / residue background probability)
  * </pre>
  * 
- * using global ('Uniprot') background frequencies for residues.
+ * Sub-class implementations use either global ('Uniprot') or local
+ * ('alignment') background frequencies.
  * 
  * @author tzvanaalten
- *
+ * @author gmcarstairs
  */
-public class HMMERColourScheme extends ResidueColourScheme
+public abstract class HmmerColourScheme extends ResidueColourScheme
 {
-  /*
-   * The highest possible log ratio is when match emission probability in
-   * the HMM model is 1, and background (for W) is 0.0109 giving
-   * log(1/0.0109) = log(91.743) = 4.519
-   */
-  private static final float MAX_LOG_RATIO = 4.519f;
+  private static final Color INSERTION_COLOUR = new Color(230, 0, 0); // reddish
 
-  private static final Color REDDISH = new Color(230, 0, 0);
+  private HiddenMarkovModel hmm;
 
-  HiddenMarkovModel hmm;
+  private Map<Character, Float> frequencies;
 
   /**
    * Constructor given a Hidden Markov Model
    * 
    * @param markov
    */
-  public HMMERColourScheme(HiddenMarkovModel markov)
+  public HmmerColourScheme(HiddenMarkovModel markov)
   {
     hmm = markov;
   }
@@ -55,7 +52,7 @@ public class HMMERColourScheme extends ResidueColourScheme
   /**
    * Default constructor (required by ColourSchemes.loadColourSchemes)
    */
-  public HMMERColourScheme()
+  public HmmerColourScheme()
   {
   }
 
@@ -81,7 +78,7 @@ public class HMMERColourScheme extends ResidueColourScheme
    */
   private Color findColour(char symbol, int column)
   {
-    if (hmm == null || Comparison.isGap(symbol))
+    if (getHmm() == null || Comparison.isGap(symbol))
     {
       return Color.white;
     }
@@ -90,28 +87,27 @@ public class HMMERColourScheme extends ResidueColourScheme
       symbol = Character.toUpperCase(symbol);
     }
 
-    double prob = hmm.getMatchEmissionProbability(column, symbol);
+    double prob = getHmm().getMatchEmissionProbability(column, symbol);
     Float freq = 0f;
-    String alpha = hmm.getAlphabetType();
-    if (!ResidueProperties.backgroundFrequencies.get(alpha)
-            .containsKey(symbol))
+
+    if (!frequencies.containsKey(symbol))
     {
       return Color.WHITE;
     }
     else
     {
-      freq = ResidueProperties.backgroundFrequencies.get(alpha).get(symbol);
+      freq = frequencies.get(symbol);
     }
     if (prob == 0D)
     {
-      return REDDISH;
+      return INSERTION_COLOUR;
     }
     double value = Math.log(prob / freq.floatValue());
     Color colour = null;
     if (value > 0)
     {
       colour = ColorUtils.getGraduatedColour((float) value, 0,
-              Color.WHITE, MAX_LOG_RATIO, Color.blue);
+              Color.WHITE, getMaxInformationScore(), Color.blue);
     }
     else if (value < 0)
     {
@@ -120,6 +116,14 @@ public class HMMERColourScheme extends ResidueColourScheme
     return colour;
   }
 
+  /**
+   * Answers the maximum possible value of information score (log ratio), for
+   * use in scaling a graduated colour range
+   * 
+   * @return
+   */
+  abstract float getMaxInformationScore();
+
   @Override
   public void alignmentChanged(AnnotatedCollectionI collection,
           Map<SequenceI, SequenceCollectionI> hiddenReps)
@@ -132,24 +136,27 @@ public class HMMERColourScheme extends ResidueColourScheme
 
   /**
    * Answers a new colour scheme instance based on the HMM of the first sequence
-   * in sg that has an HMM
+   * in ac that has an HMM
    */
   @Override
-  public ColourSchemeI getInstance(AnnotatedCollectionI sg,
+  public ColourSchemeI getInstance(AnnotatedCollectionI ac,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
-    SequenceI hmmSeq = sg.getHmmConsensus();
+    SequenceI hmmSeq = ac.getHmmConsensus();
     HiddenMarkovModel model = hmmSeq == null ? null : hmmSeq.getHMM();
 
-    HMMERColourScheme colour = new HMMERColourScheme(model);
-    return colour;
+    return newInstance(ac, model);
   }
 
-  @Override
-  public String getSchemeName()
-  {
-    return JalviewColourScheme.HMMERU.toString();
-  }
+  /**
+   * Answers a new instance of the colour scheme for the given HMM
+   * 
+   * @param ac
+   * @param model
+   * @return
+   */
+  protected abstract HmmerColourScheme newInstance(AnnotatedCollectionI ac,
+          HiddenMarkovModel model);
 
   @Override
   public boolean isSimple()
@@ -167,4 +174,19 @@ public class HMMERColourScheme extends ResidueColourScheme
     return ac.getHmmConsensus() != null;
   }
 
+  protected Map<Character, Float> getFrequencies()
+  {
+    return frequencies;
+  }
+
+  protected void setFrequencies(Map<Character, Float> frequencies)
+  {
+    this.frequencies = frequencies;
+  }
+
+  protected HiddenMarkovModel getHmm()
+  {
+    return hmm;
+  }
+
 }