complete Information Content annotation
[jalview.git] / src / jalview / renderer / AnnotationRenderer.java
index 518c179..640bf45 100644 (file)
@@ -29,12 +29,14 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.ProfilesI;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.NucleotideColourScheme;
 import jalview.schemes.ResidueProperties;
 import jalview.schemes.ZappoColourScheme;
 import jalview.util.Platform;
+import jalview.util.QuickSort;
 
 import java.awt.BasicStroke;
 import java.awt.Color;
@@ -48,6 +50,7 @@ import java.awt.geom.AffineTransform;
 import java.awt.image.ImageObserver;
 import java.util.BitSet;
 import java.util.Hashtable;
+import java.util.List;
 
 public class AnnotationRenderer
 {
@@ -57,6 +60,10 @@ public class AnnotationRenderer
 
   private static final int CHAR_Z = 'Z'; // 90
 
+  private static final int AMINO = 0;
+
+  private static final int DNA = 1;
+
   /**
    * flag indicating if timing and redraw parameter info should be output
    */
@@ -337,6 +344,95 @@ public class AnnotationRenderer
     av_ignoreGapsConsensus = av.isIgnoreGapsConsensus();
   }
 
+  public int[] getHMMProfileFor(AlignmentAnnotation aa, int column,
+          boolean removeBelowBackground)
+  {
+
+    HiddenMarkovModel hmm;
+    hmm = aa.getHMM();
+    int size = 0;
+    int alphabet = 0;
+    String alph = hmm.getAlphabetType();
+    if (alph.equals("amino"))
+    {
+      size = 20;
+      alphabet = AMINO;
+    }
+    else if (alph.equals("DNA"))
+    {
+      size = 4;
+      alphabet = DNA;
+    }
+
+    char symbols[] = new char[size];
+    int values[] = new int[size];
+
+    List<Character> charList = hmm.getSymbols();
+
+    int i = 0;
+    for (char character : charList)
+    {
+      symbols[i] = character;
+      i++;
+    }
+
+    Integer totalCount = 0;
+    for (int j = 0; j < size; j++)
+    {
+      Double value;
+      char symbol = symbols[j];
+      value = hmm.getMatchEmissionProbability(column, symbol);
+      double freq;
+
+      if (alphabet == AMINO && removeBelowBackground)
+      {
+        freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol);
+        if (value < freq)
+        {
+          value = 0d;
+        }
+      }
+      else if (alphabet == DNA && removeBelowBackground)
+      {
+        freq = ResidueProperties.nucleotideBackgroundFrequencies
+                .get(symbol);
+        if (value < freq)
+        {
+          value = 0d;
+        }
+      }
+      value = value * 10000;
+      values[j] = value.intValue();
+      totalCount += value.intValue();
+    }
+
+    QuickSort.sort(values, symbols);
+
+    int[] profile = new int[3 + size * 2];
+
+    profile[0] = AlignmentAnnotation.SEQUENCE_PROFILE;
+    profile[1] = size;
+    profile[2] = totalCount;
+
+    if (totalCount != 0)
+    {
+      int arrayPos = 3;
+      for (int k = size - 1; k >= 0; k--)
+      {
+        Double percentage;
+        Integer value = values[k];
+        percentage = (value.doubleValue() / totalCount.doubleValue())
+                * 100d;
+        profile[arrayPos] = symbols[k];
+        profile[arrayPos + 1] = percentage.intValue();
+        arrayPos += 2;
+      }
+    }
+
+    return profile;
+
+  }
+
   /**
    * Returns profile data; the first element is the profile type, the second is
    * the number of distinct values, the third the total count, and the remainder
@@ -352,6 +448,10 @@ public class AnnotationRenderer
     // properties/rendering attributes as a global 'alignment group' which holds
     // all vis settings for the alignment as a whole rather than a subset
     //
+    if (aa.label.startsWith("Information"))
+    {
+      return getHMMProfileFor(aa, column, true);
+    }
     if (aa.autoCalculated
             && (aa.label.startsWith("Consensus") || aa.label
                     .startsWith("cDNA Consensus")))