JAL-2938 revisions to implementation details
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 30 Mar 2018 09:42:33 +0000 (10:42 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 30 Mar 2018 09:42:33 +0000 (10:42 +0100)
src/jalview/schemes/HmmerColourScheme.java
src/jalview/schemes/HmmerGlobalBackground.java
src/jalview/schemes/HmmerLocalBackground.java
test/jalview/schemes/HmmerGlobalBackgroundTest.java
test/jalview/schemes/HmmerLocalBackgroundTest.java

index d31f0e1..9ea468d 100644 (file)
@@ -12,10 +12,10 @@ import java.util.Map;
 
 /**
  * Base class for colour schemes based on a selected Hidden Markov Model. The
- * colour is
+ * colour is with reference to an HMM consensus sequence and HMM profile
  * <ul>
  * <li>white for a gap</li>
- * <li>red for an insertion</li>
+ * <li>red for an insertion (position is gapped in the HMM consensus)</li>
  * <li>orange for negative information content</li>
  * <li>white to blue for increasing information content</li>
  * </ul>
@@ -35,18 +35,26 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
 {
   private static final Color INSERTION_COLOUR = new Color(230, 0, 0); // reddish
 
+  /*
+   * the aligned HMM consensus sequence to use as reference for colouring
+   */
+  private SequenceI hmmSeq;
+
   private HiddenMarkovModel hmm;
 
   private Map<Character, Float> frequencies;
 
   /**
-   * Constructor given a Hidden Markov Model
+   * Constructor given a Hidden Markov Model consensus sequence. This provides
+   * the HMM profile from which we can read the emission probabilities that
+   * determine the colour.
    * 
-   * @param markov
+   * @param consensusSeq
    */
-  public HmmerColourScheme(HiddenMarkovModel markov)
+  public HmmerColourScheme(SequenceI consensusSeq)
   {
-    hmm = markov;
+    hmmSeq = consensusSeq;
+    hmm = hmmSeq == null ? null : hmmSeq.getHMM();
   }
 
   /**
@@ -57,10 +65,10 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
   }
 
   @Override
-  public Color findColour(char symbol, int position, SequenceI seq,
+  public Color findColour(char symbol, int column, SequenceI seq,
           String consensusResidue, float pid)
   {
-    return findColour(symbol, position);
+    return findColour(symbol, column);
   }
 
   /**
@@ -82,6 +90,10 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
     {
       return Color.white;
     }
+    if (Comparison.isGap(hmmSeq.getCharAt(column)))
+    {
+      return INSERTION_COLOUR;
+    }
     if (Character.isLowerCase(symbol))
     {
       symbol = Character.toUpperCase(symbol);
@@ -100,19 +112,22 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
     {
       freq = frequencies.get(symbol);
     }
-    if (prob == 0D)
-    {
-      return INSERTION_COLOUR;
-    }
-    double value = Math.log(prob / freq.floatValue());
-    Color colour = null;
-    if (value < 0)
+
+    /*
+     * Orange if match emission probability is less than background probability
+     */
+    double infoRatio = prob / freq.floatValue();
+    Color colour = Color.ORANGE;
+    if (infoRatio >= 1)
     {
-      return Color.ORANGE;
+      /*
+       * log-scale graduated shade of blue if prob is greater than background  
+       */
+      float infoLog = (float) Math.log(infoRatio);
+      colour = ColorUtils.getGraduatedColour(infoLog, 0, Color.WHITE,
+              getMaxInformationScore(), Color.blue);
     }
 
-    colour = ColorUtils.getGraduatedColour((float) value, 0, Color.WHITE,
-            getMaxInformationScore(), Color.blue);
     return colour;
   }
 
@@ -124,16 +139,6 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
    */
   abstract float getMaxInformationScore();
 
-  @Override
-  public void alignmentChanged(AnnotatedCollectionI collection,
-          Map<SequenceI, SequenceCollectionI> hiddenReps)
-  {
-    /*
-     * ? no need to do anything if alignment is adjusted
-     * since findColour() handles everything 
-     */
-  }
-
   /**
    * Answers a new colour scheme instance based on the HMM of the first sequence
    * in ac that has an HMM
@@ -142,21 +147,16 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
   public ColourSchemeI getInstance(AnnotatedCollectionI ac,
           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
   {
-    SequenceI hmmSeq = ac.getHmmConsensus();
-    HiddenMarkovModel model = hmmSeq == null ? null : hmmSeq.getHMM();
-
-    return newInstance(ac, model);
+    return newInstance(ac);
   }
 
   /**
    * 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);
+  protected abstract HmmerColourScheme newInstance(AnnotatedCollectionI ac);
 
   @Override
   public boolean isSimple()
@@ -189,4 +189,8 @@ public abstract class HmmerColourScheme extends ResidueColourScheme
     return hmm;
   }
 
+  protected SequenceI getHmmSequence()
+  {
+    return hmmSeq;
+  }
 }
index e1d00bb..d5508f1 100644 (file)
@@ -1,7 +1,6 @@
 package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
-import jalview.datamodel.HiddenMarkovModel;
 
 /**
  * An HMM colour scheme that uses global ('Uniprot') background frequencies for
@@ -23,11 +22,12 @@ public class HmmerGlobalBackground extends HmmerColourScheme
    * 
    * @param markov
    */
-  public HmmerGlobalBackground(HiddenMarkovModel markov)
+  public HmmerGlobalBackground(AnnotatedCollectionI ac)
   {
-    super(markov);
-    String alphabetType = markov == null ? ResidueProperties.ALPHABET_AMINO
-            : markov.getAlphabetType();
+    super(ac.getHmmConsensus());
+    String alphabetType = getHmm() == null
+            ? ResidueProperties.ALPHABET_AMINO
+            : getHmm().getAlphabetType();
     setFrequencies(
             ResidueProperties.backgroundFrequencies.get(alphabetType));
   }
@@ -46,10 +46,9 @@ public class HmmerGlobalBackground extends HmmerColourScheme
   }
 
   @Override
-  protected HmmerColourScheme newInstance(AnnotatedCollectionI ac,
-          HiddenMarkovModel model)
+  protected HmmerColourScheme newInstance(AnnotatedCollectionI ac)
   {
-    return new HmmerGlobalBackground(model);
+    return new HmmerGlobalBackground(ac);
   }
 
   @Override
index b878b9e..d7a5e65 100644 (file)
@@ -1,10 +1,11 @@
 package jalview.schemes;
 
 import jalview.datamodel.AnnotatedCollectionI;
-import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.ResidueCount;
+import jalview.datamodel.SequenceI;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -24,11 +25,10 @@ public class HmmerLocalBackground extends HmmerColourScheme
    * 
    * @param markov
    */
-  public HmmerLocalBackground(AnnotatedCollectionI sg,
-          HiddenMarkovModel markov)
+  public HmmerLocalBackground(AnnotatedCollectionI ac)
   {
-    super(markov);
-    countFrequencies(sg);
+    super(ac.getHmmConsensus());
+    countFrequencies(ac);
   }
 
   /**
@@ -46,13 +46,30 @@ public class HmmerLocalBackground extends HmmerColourScheme
 
   /**
    * Counts and stores the relative frequency of every residue in the alignment
+   * (apart from any HMM consensus sequences)
    * 
    * @param sg
    */
   public void countFrequencies(AnnotatedCollectionI sg)
   {
+    // TODO or total counts in Consensus Profile (how do we get at it?)?
     Map<Character, Float> freqs = new HashMap<>();
-    ResidueCount counts = new ResidueCount(sg.getSequences());
+
+    /*
+     * count symbols, excluding any HMM consensus sequences
+     */
+    ResidueCount counts = new ResidueCount();
+    List<SequenceI> seqs = sg.getSequences();
+    for (SequenceI seq : seqs)
+    {
+      if (!seq.isHMMConsensusSequence())
+      {
+        for (char c : seq.getSequence())
+        {
+          counts.add(c);
+        }
+      }
+    }
     int total = counts.getTotalResidueCount(); // excludes gaps
 
     for (char symbol : counts.getSymbolCounts().symbols)
@@ -73,9 +90,8 @@ public class HmmerLocalBackground extends HmmerColourScheme
   }
 
   @Override
-  protected HmmerColourScheme newInstance(AnnotatedCollectionI ac,
-          HiddenMarkovModel model)
+  protected HmmerColourScheme newInstance(AnnotatedCollectionI ac)
   {
-    return new HmmerLocalBackground(ac, model);
+    return new HmmerLocalBackground(ac);
   }
 }
index b417482..13bf47b 100644 (file)
@@ -2,6 +2,9 @@ package jalview.schemes;
 
 import static org.testng.Assert.assertEquals;
 
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
 import jalview.io.DataSourceType;
 import jalview.io.HMMFile;
 
@@ -19,7 +22,10 @@ public class HmmerGlobalBackgroundTest {
     HMMFile file = new HMMFile("test/jalview/io/test_PKinase_hmm.txt",
             DataSourceType.FILE);
 
-    ColourSchemeI scheme = new HmmerGlobalBackground(file.getHMM());
+    SequenceI hmmSeq = file.getSeqsAsArray()[0];
+    AlignmentI al = new Alignment(new SequenceI[] { hmmSeq });
+    al.setHmmConsensus(hmmSeq);
+    ColourSchemeI scheme = new HmmerGlobalBackground(al);
 
     /*
      * 'A' in column 1, node 2, match emission 2.77204
index 991adb5..7467ab2 100644 (file)
@@ -33,9 +33,12 @@ public class HmmerLocalBackgroundTest {
      */
     SequenceI seq1 = new Sequence("seq1", "AAMMMKKKVV");
     SequenceI seq2 = new Sequence("seq2", "aAM-QKRSSSL");
-    AnnotatedCollectionI ac = new Alignment(new SequenceI[] { seq1, seq2 });
-    ColourSchemeI scheme = new HmmerLocalBackground(ac,
-            file.getHMM());
+    SequenceI hmmSeq = file.getSeqsAsArray()[0];
+    AnnotatedCollectionI ac = new Alignment(
+            new SequenceI[]
+            { hmmSeq, seq1, seq2 });
+    ac.setHmmConsensus(hmmSeq);
+    ColourSchemeI scheme = new HmmerLocalBackground(ac);
 
     /*
      * 'A' in column 1, node 2, match emission 2.77204