JAL-2629 hmm search UI and structural improvements, inclusion thresholds
[jalview.git] / src / jalview / schemes / HMMMatchScoreColourScheme.java
index 36f66d0..96eb26a 100644 (file)
@@ -12,15 +12,22 @@ import java.io.BufferedReader;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 
+
+
 public class HMMMatchScoreColourScheme extends ResidueColourScheme
 {
   
-  private Map<Character, Map<String, Double>> probabilities;
+  private Map<Character, Map<Integer, Map<String, Double>>> probabilities;
+
+  private List<Integer> ranges;
+
+  private static double binSize;
 
   public class MatchProbReader
   {
@@ -32,6 +39,7 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
               new FileReader("resources/ProbabilityOfMatch"));
     }
     
+    /*
     public Map<Character, Map<String, Double>>  getProbabilities() throws IOException
     {
       Map<Character, Map<String, Double>> probabilities = new HashMap<>();
@@ -55,12 +63,62 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
                           .valueOf(contents[i].replaceAll("\\ ", "")));
         }
         line = reader.readLine();
-
+    
       }
       reader.close();
       return probabilities;
     }
+    */
     
+    public Map<Character, Map<Integer, Map<String, Double>>> getProbabilities()
+            throws IOException
+    {
+
+      Map<Character, Map<Integer, Map<String, Double>>> probabilities = new HashMap<>();
+
+      ranges = new ArrayList<>();
+      ranges.add(0);
+
+      binSize = Double.valueOf((reader.readLine().replaceAll("\\ ", "")));
+      String line = reader.readLine();
+      char c = line.charAt(0);
+
+      while (line != null)
+      {
+        line = reader.readLine();
+        while (line != null && line.split("\\,").length != 1)
+        {
+          String[] llrs = line.split("\\,");
+          String[] counts = reader.readLine().split("\\,");
+          int range = Integer.valueOf(llrs[0]);
+
+          if (!ranges.contains(range))
+          {
+            ranges.add(range);
+          }
+          if (!probabilities.containsKey(c))
+          {
+            probabilities.put(c, new HashMap<>());
+          }
+          probabilities.get(c).put(range, new HashMap<>());
+
+          for (int i = 1; i < llrs.length; i++)
+          {
+            probabilities.get(c).get(range).put(
+                    llrs[i].replaceAll("\\ ", ""),
+                    Double.valueOf(counts[i].replaceAll("\\ ", "")));
+          }
+
+          line = reader.readLine();
+        }
+        if (line != null)
+        {
+          c = line.charAt(0);
+        }
+      }
+
+      return probabilities;
+    }
     
   }
 
@@ -109,10 +167,14 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
   public Color findColour(char symbol, int column, SequenceI seq,
           String consensusResidue, float pid)
   {
-    return findColour(symbol, column);
+    if (seq == null)
+    {
+      return null;
+    }
+    return findColour(symbol, column, seq.gapMap().length);
   }
 
-  // TODO change
+  // TODO change documentation
   /**
    * Returns the colour at a particular symbol at a column in the alignment:
    * <ul>
@@ -126,7 +188,7 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
    * @param column
    * @return
    */
-  private Color findColour(char symbol, int column)
+  private Color findColour(char symbol, int column, int length)
   {
     if (getHmm() == null || Comparison.isGap(symbol))
     {
@@ -141,11 +203,29 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
       symbol = Character.toUpperCase(symbol);
     }
 
-    double llr = Math
-            .log(getHmm().getMatchEmissionProbability(column, symbol)
-                    / hmm.getBackgroundFrequencies().get(symbol));
+    double prob = 0;
+    if (hmm.getBackgroundFrequencies().containsKey(symbol))
+    {
+      int lengthBin = getLengthBin(length);
+
+      double llr = Math
+              .log(getHmm().getMatchEmissionProbability(column, symbol)
+                      / hmm.getBackgroundFrequencies().get(symbol));
+
+      if (!probabilities.containsKey(symbol)
+              || !probabilities.get(symbol).get(lengthBin)
+              .containsKey(format(llr)))
+      {
+        return new Color(140, 140, 140);
+      }
+
 
-    double prob = probabilities.get(symbol).get(format(llr));
+      prob = probabilities.get(symbol).get(lengthBin).get(format(llr));
+    }
+    else
+    {
+      return new Color(140, 140, 140);
+    }
 
     Color colour = Color.ORANGE;
     if (prob >= 0.5)
@@ -166,12 +246,25 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
 
   public static String format(Double d)
   {
-    String formatted = String.format("%.1f", d);
+    String formatArg = String.valueOf(binSize);
+
+    // if bin size, need format "%.n" where n is number of decimal places
+    if (binSize < 1)
+    {
+      formatArg = "." + formatArg.split("\\.")[1].length();
+    }
+
+    Double rounded = Math.round(d / binSize) * binSize;
+    String formatted = String.format("%" + formatArg + "f", rounded);
+
+    // format sometimes returns a number rounded to 0 as -0
+    // this ensures output will always be 0
     if (Double.valueOf(formatted) == 0)
     {
       formatted = "0";
     }
     return formatted;
+
   }
 
   /**
@@ -224,13 +317,14 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
   }
 
   /**
-   * Answers true if the sequence collection has an HMM consensus sequence, else
-   * false
+   * Answers true if the sequence collection has an HMM consensus sequence and
+   * that the first HMM sequence contains background frequencies, else false
    */
   @Override
   public boolean isApplicableTo(AnnotatedCollectionI ac)
   {
-    return !ac.getHmmSequences().isEmpty();
+    return !ac.getHmmSequences().isEmpty() && ac.getHmmSequences().get(0)
+            .getHMM().getBackgroundFrequencies() != null;
   }
 
   protected Map<Character, Float> getFrequencies()
@@ -259,7 +353,17 @@ public class HMMMatchScoreColourScheme extends ResidueColourScheme
     return JalviewColourScheme.HMMMatchScore.toString();
   }
 
-  
+  private int getLengthBin(int l)
+  {
+    for (int i = 1; i < ranges.size(); i++)
+    {
+      if (l >= ranges.get(i - 1) && l < ranges.get(i))
+      {
+        return ranges.get(i);
+      }
+    }
+    return -1;
+  }
 }