JAL-2629 add file that should have been in previous commit
authortva <tva@10.205.251.175>
Fri, 28 Jun 2019 12:33:04 +0000 (13:33 +0100)
committertva <tva@10.205.251.175>
Fri, 28 Jun 2019 12:33:04 +0000 (13:33 +0100)
src/jalview/schemes/HMMMatchScoreColourScheme.java [new file with mode: 0644]

diff --git a/src/jalview/schemes/HMMMatchScoreColourScheme.java b/src/jalview/schemes/HMMMatchScoreColourScheme.java
new file mode 100644 (file)
index 0000000..36f66d0
--- /dev/null
@@ -0,0 +1,265 @@
+package jalview.schemes;
+
+import jalview.api.AlignViewportI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.util.ColorUtils;
+import jalview.util.Comparison;
+
+import java.awt.Color;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+public class HMMMatchScoreColourScheme extends ResidueColourScheme
+{
+  
+  private Map<Character, Map<String, Double>> probabilities;
+
+  public class MatchProbReader
+  {
+    private BufferedReader reader;
+    
+    MatchProbReader() throws FileNotFoundException
+    {
+      reader = new BufferedReader(
+              new FileReader("resources/ProbabilityOfMatch"));
+    }
+    
+    public Map<Character, Map<String, Double>>  getProbabilities() throws IOException
+    {
+      Map<Character, Map<String, Double>> probabilities = new HashMap<>();
+      
+      String[] alphabet = reader.readLine().split("\\,");
+      for (int i = 1; i < alphabet.length - 1; i++)
+      {
+        probabilities.put(alphabet[i].replaceAll("\\ ", "").charAt(0),
+                new HashMap<>());
+      }
+      
+      String line = reader.readLine();
+      while(line != null)
+      {
+        String[] contents = line.split("\\,");
+        
+        for(int i = 1; i < contents.length; i++)
+        {
+          probabilities.get(alphabet[i].replaceAll("\\ ", "").charAt(0))
+                  .put(contents[0], Double
+                          .valueOf(contents[i].replaceAll("\\ ", "")));
+        }
+        line = reader.readLine();
+
+      }
+      reader.close();
+      return probabilities;
+    }
+    
+    
+  }
+
+  private static final Color INSERTION_COLOUR = Color.white;
+
+  /*
+   * 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 list of Hidden Markov Model consensus sequences. The
+   * first sequence provides the HMM profile from which we can read the emission
+   * probabilities that determine the colour.
+   * 
+   * @param hmmSeqs
+   * @throws IOException
+   */
+  public HMMMatchScoreColourScheme(List<SequenceI> hmmSeqs)
+  {
+    hmmSeq = hmmSeqs.isEmpty() ? null : hmmSeqs.get(0);
+    hmm = hmmSeq == null ? null : hmmSeq.getHMM();
+
+    try
+    {
+      MatchProbReader probabilityReader = new MatchProbReader();
+      probabilities = probabilityReader.getProbabilities();
+    } catch (IOException e)
+    {
+      System.out.println(e.getStackTrace());
+    }
+  }
+
+  /**
+   * Default constructor (required by ColourSchemes.loadColourSchemes)
+   */
+  public HMMMatchScoreColourScheme()
+  {
+  }
+
+  @Override
+  public Color findColour(char symbol, int column, SequenceI seq,
+          String consensusResidue, float pid)
+  {
+    return findColour(symbol, column);
+  }
+
+  // TODO change
+  /**
+   * Returns the colour at a particular symbol at a column in the alignment:
+   * <ul>
+   * <li>white for a gap</li>
+   * <li>red for an insertion</li>
+   * <li>orange for negative information content</li>
+   * <li>white to blue for increasing information content</li>
+   * </ul>
+   * 
+   * @param symbol
+   * @param column
+   * @return
+   */
+  private Color findColour(char symbol, int column)
+  {
+    if (getHmm() == null || Comparison.isGap(symbol))
+    {
+      return Color.white;
+    }
+    if (Comparison.isGap(hmmSeq.getCharAt(column)))
+    {
+      return INSERTION_COLOUR;
+    }
+    if (Character.isLowerCase(symbol))
+    {
+      symbol = Character.toUpperCase(symbol);
+    }
+
+    double llr = Math
+            .log(getHmm().getMatchEmissionProbability(column, symbol)
+                    / hmm.getBackgroundFrequencies().get(symbol));
+
+    double prob = probabilities.get(symbol).get(format(llr));
+
+    Color colour = Color.ORANGE;
+    if (prob >= 0.5)
+    {
+
+      colour = ColorUtils.getGraduatedColour((float) prob, 0.5f,
+              Color.WHITE, 1f,
+              Color.blue);
+    }
+    else
+    {
+      colour = ColorUtils.getGraduatedColour((float) prob, 0f, Color.red,
+              0.5f, Color.WHITE);
+    }
+
+    return colour;
+  }
+
+  public static String format(Double d)
+  {
+    String formatted = String.format("%.1f", d);
+    if (Double.valueOf(formatted) == 0)
+    {
+      formatted = "0";
+    }
+    return formatted;
+  }
+
+  /**
+   * Answers the maximum possible value of information score (log ratio), for use
+   * in scaling a graduated colour range
+   * 
+   * @return
+   */
+  protected float getMaxInformationScore()
+  {
+    return 0f;
+  }
+
+  /**
+   * Answers a new colour scheme instance based on the HMM of the first sequence
+   * in ac that has an HMM
+   */
+  @Override
+  public ColourSchemeI getInstance(AlignViewportI viewport,
+          AnnotatedCollectionI ac)
+  {
+    return newInstance(ac);
+  }
+
+  /**
+   * Constructor given a sequence collection
+   * 
+   * @param ac
+   */
+  public HMMMatchScoreColourScheme(AnnotatedCollectionI ac)
+  {
+    this(ac.getHmmSequences());
+  }
+
+  /**
+   * Answers a new instance of the colour scheme for the given HMM
+   * 
+   * @param ac
+   * @return
+   */
+  protected HMMMatchScoreColourScheme newInstance(AnnotatedCollectionI ac)
+  {
+    return new HMMMatchScoreColourScheme(ac);
+  }
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
+  }
+
+  /**
+   * Answers true if the sequence collection has an HMM consensus sequence, else
+   * false
+   */
+  @Override
+  public boolean isApplicableTo(AnnotatedCollectionI ac)
+  {
+    return !ac.getHmmSequences().isEmpty();
+  }
+
+  protected Map<Character, Float> getFrequencies()
+  {
+    return frequencies;
+  }
+
+  protected void setFrequencies(Map<Character, Float> frequencies)
+  {
+    this.frequencies = frequencies;
+  }
+
+  protected HiddenMarkovModel getHmm()
+  {
+    return hmm;
+  }
+
+  protected SequenceI getHmmSequence()
+  {
+    return hmmSeq;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.HMMMatchScore.toString();
+  }
+
+  
+}
+
+