JAL-2629 storage and lifecycle of alignment/group HMM annotations revised
[jalview.git] / src / jalview / analysis / AAFrequency.java
index f77517c..3e59274 100755 (executable)
@@ -194,10 +194,10 @@ public class AAFrequency
    * @param end
    *          The alignment column on which the last profile is based.
    * @param saveFullProfile
-   *          Flag for saving the counts for each profile
+   *          if true, all residue counts are saved (enables profile logo)
    * @param removeBelowBackground
-   *          Flag for removing any characters with a match emission probability
-   *          less than its background frequency
+   *          if true, symbols with a match emission probability less than
+   *          background frequency are ignored
    * @return
    */
   public static ProfilesI calculateHMMProfiles(final HiddenMarkovModel hmm,
@@ -205,11 +205,12 @@ public class AAFrequency
           boolean removeBelowBackground, boolean infoLetterHeight)
   {
     ProfileI[] result = new ProfileI[width];
-    int symbolCount = hmm.getNumberOfSymbols();
+    char[] symbols = hmm.getSymbols().toCharArray();
+    int symbolCount = symbols.length;
     for (int column = start; column < end; column++)
     {
       ResidueCount counts = new ResidueCount();
-      for (char symbol : hmm.getSymbols())
+      for (char symbol : symbols)
       {
         int value = getAnalogueCount(hmm, column, symbol,
                 removeBelowBackground, infoLetterHeight);
@@ -352,7 +353,7 @@ public class AAFrequency
    */
   public static float completeInformation(AlignmentAnnotation information,
           ProfilesI profiles, int startCol, int endCol, long nseq,
-          Float currentMax)
+          float currentMax)
   {
     // long now = System.currentTimeMillis();
     if (information == null || information.annotations == null
@@ -365,54 +366,47 @@ public class AAFrequency
       return 0;
     }
 
-    Float max = 0f;
+    float max = 0f;
+    SequenceI hmmSeq = information.sequenceRef;
+    HiddenMarkovModel hmm = hmmSeq.getHMM();
 
-    for (int i = startCol; i < endCol; i++)
+    for (int column = startCol; column < endCol; column++)
     {
-      ProfileI profile = profiles.get(i);
+      ProfileI profile = profiles.get(column);
       if (profile == null)
       {
         /*
          * happens if sequences calculated over were 
          * shorter than alignment width
          */
-        information.annotations[i] = null;
-        return 0;
+        information.annotations[column] = null;
+        return 0f;
       }
       
-      SequenceI hmmSeq = information.sequenceRef;
-      
-      HiddenMarkovModel hmm = hmmSeq.getHMM();
-      
-      float value = hmm.getInformationContent(i);
-
-      if (value > max)
+      float value = hmm.getInformationContent(column);
+      boolean isNaN = Float.isNaN(value);
+      if (!isNaN)
       {
-        max = value;
+        max = Math.max(max, value);
       }
 
-      String description = value + " bits";
-      information.annotations[i] = new Annotation(
+      String description = isNaN ? null
+              : String.format("%.4f bits", value);
+      information.annotations[column] = new Annotation(
               Character.toString(Character
-                      .toUpperCase(hmm.getConsensusAtAlignColumn(i))),
+                      .toUpperCase(hmm.getConsensusAtAlignColumn(column))),
               description, ' ', value);
     }
-    if (max > currentMax)
-    {
-      information.graphMax = max;
-      return max;
-    }
-    else
-    {
-      information.graphMax = currentMax;
-      return currentMax;
-    }
+
+    max = Math.max(max, currentMax);
+    information.graphMax = max;
+    return max;
   }
 
   /**
-   * Derive the gap count annotation row.
+   * Derive the occupancy count annotation
    * 
-   * @param gaprow
+   * @param occupancy
    *          the annotation row to add annotations to
    * @param profiles
    *          the source consensus data
@@ -421,11 +415,11 @@ public class AAFrequency
    * @param endCol
    *          end column (exclusive)
    */
-  public static void completeGapAnnot(AlignmentAnnotation gaprow,
+  public static void completeOccupancyAnnot(AlignmentAnnotation occupancy,
           ProfilesI profiles, int startCol, int endCol, long nseq)
   {
-    if (gaprow == null || gaprow.annotations == null
-            || gaprow.annotations.length < endCol)
+    if (occupancy == null || occupancy.annotations == null
+            || occupancy.annotations.length < endCol)
     {
       /*
        * called with a bad alignment annotation row 
@@ -434,8 +428,8 @@ public class AAFrequency
       return;
     }
     // always set ranges again
-    gaprow.graphMax = nseq;
-    gaprow.graphMin = 0;
+    occupancy.graphMax = nseq;
+    occupancy.graphMin = 0;
     double scale = 0.8 / nseq;
     for (int i = startCol; i < endCol; i++)
     {
@@ -446,7 +440,7 @@ public class AAFrequency
          * happens if sequences calculated over were 
          * shorter than alignment width
          */
-        gaprow.annotations[i] = null;
+        occupancy.annotations[i] = null;
         return;
       }
 
@@ -454,7 +448,8 @@ public class AAFrequency
 
       String description = "" + gapped;
 
-      gaprow.annotations[i] = new Annotation("", description, '\0', gapped,
+      occupancy.annotations[i] = new Annotation("", description, '\0',
+              gapped,
               jalview.util.ColorUtils.bleachColour(Color.DARK_GRAY,
                       (float) scale * gapped));
     }
@@ -867,15 +862,15 @@ public class AAFrequency
     {
       return null;
     }
-    int size = hmm.getNumberOfSymbols();
+    String alphabet = hmm.getSymbols();
+    int size = alphabet.length();
     char symbols[] = new char[size];
     int values[] = new int[size];
-    List<Character> charList = hmm.getSymbols();
     int totalCount = 0;
 
     for (int i = 0; i < size; i++)
     {
-      char symbol = charList.get(i);
+      char symbol = alphabet.charAt(i);
       symbols[i] = symbol;
       int value = getAnalogueCount(hmm, column, symbol,
               removeBelowBackground, infoHeight);