JAL-2629 add option to set HMM Logo letter height to info content
authortzvanaalten <tzvanaalten@172.17.105.62>
Mon, 28 Aug 2017 16:21:39 +0000 (17:21 +0100)
committertzvanaalten <tzvanaalten@172.17.105.62>
Mon, 28 Aug 2017 16:21:39 +0000 (17:21 +0100)
resources/lang/Messages.properties
src/jalview/analysis/AAFrequency.java
src/jalview/api/AlignViewportI.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/gui/AnnotationLabels.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/workers/InformationThread.java
test/jalview/analysis/AAFrequencyTest.java

index be20995..b5547cb 100644 (file)
@@ -1379,3 +1379,4 @@ label.alignment = Alignment
 label.groups_and_alignment = All groups and alignment
 label.groups = All groups
 label.selected_group = Selected group
+label.use_info_for_height = Use Information Content as Letter Height
index 72b3d00..cc4f8f4 100755 (executable)
@@ -224,7 +224,7 @@ public class AAFrequency
    */
   public static ProfilesI calculateHMMProfiles(final HiddenMarkovModel hmm,
           int width, int start, int end, boolean saveFullProfile,
-          boolean removeBelowBackground)
+          boolean removeBelowBackground, boolean infoLetterHeight)
   {
     ProfileI[] result = new ProfileI[width];
     int symbolCount = hmm.getNumberOfSymbols();
@@ -234,7 +234,7 @@ public class AAFrequency
       for (char symbol : hmm.getSymbols())
       {
         int value = getAnalogueCount(hmm, column, symbol,
-                removeBelowBackground);
+                removeBelowBackground, infoLetterHeight);
         counts.put(symbol, value);
       }
       int maxCount = counts.getModalCount();
@@ -372,10 +372,9 @@ public class AAFrequency
    * @param nseq
    *          number of sequences
    */
-  public static void completeInformation(AlignmentAnnotation information,
-          ProfilesI profiles, int startCol, int endCol,
-          boolean ignoreBelowBackground,
-          boolean showSequenceLogo, long nseq)
+  public static float completeInformation(AlignmentAnnotation information,
+          ProfilesI profiles, int startCol, int endCol, long nseq,
+          Float currentMax)
   {
     // long now = System.currentTimeMillis();
     if (information == null || information.annotations == null
@@ -385,7 +384,7 @@ public class AAFrequency
        * called with a bad alignment annotation row 
        * wait for it to be initialised properly
        */
-      return;
+      return 0;
     }
 
     Float max = 0f;
@@ -400,7 +399,7 @@ public class AAFrequency
          * shorter than alignment width
          */
         information.annotations[i] = null;
-        return;
+        return 0;
       }
 
       HiddenMarkovModel hmm;
@@ -422,9 +421,16 @@ public class AAFrequency
                       .toUpperCase(hmm.getConsensusAtAlignColumn(i))),
               description, ' ', value);
     }
-    information.graphMax = max;
-    // long elapsed = System.currentTimeMillis() - now;
-    // System.out.println(-elapsed);
+    if (max > currentMax)
+    {
+      information.graphMax = max;
+      return max;
+    }
+    else
+    {
+      information.graphMax = currentMax;
+      return currentMax;
+    }
   }
 
   /**
@@ -898,7 +904,7 @@ public class AAFrequency
    * @return
    */
   public static int[] extractHMMProfile(HiddenMarkovModel hmm, int column,
-          boolean removeBelowBackground)
+          boolean removeBelowBackground, boolean infoHeight)
   {
 
     if (hmm != null)
@@ -914,7 +920,7 @@ public class AAFrequency
         char symbol = charList.get(i);
         symbols[i] = symbol;
         int value = getAnalogueCount(hmm, column, symbol,
-                removeBelowBackground);
+                removeBelowBackground, infoHeight);
         values[i] = value;
         totalCount += value;
       }
@@ -967,7 +973,7 @@ public class AAFrequency
    * @return
    */
   static int getAnalogueCount(HiddenMarkovModel hmm, int column,
-          char symbol, boolean removeBelowBackground)
+          char symbol, boolean removeBelowBackground, boolean infoHeight)
   {
     Double value;
 
@@ -981,6 +987,11 @@ public class AAFrequency
       return 0;
     }
 
+    if (infoHeight)
+    {
+      value = value * (Math.log(value / freq) / Math.log(2));
+    }
+
     value = value * 10000;
     return Math.round(value.floatValue());
   }
index a35c2a4..96f9313 100644 (file)
@@ -529,4 +529,6 @@ public interface AlignViewportI extends ViewStyleI
    */
   void updateInformation(AlignmentViewPanel ap);
 
+  boolean isInfoLetterHeight();
+
 }
index 6db870c..c1443ef 100755 (executable)
@@ -103,6 +103,8 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   private boolean ignoreBelowBackground = true;
 
+  private boolean infoLetterHeight = false;
+
   /**
    * consensus calculation property
    */
@@ -222,6 +224,7 @@ public class SequenceGroup implements AnnotatedCollectionI
       width = seqsel.width;
       ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus;
       ignoreBelowBackground = seqsel.ignoreBelowBackground;
+      infoLetterHeight = seqsel.infoLetterHeight;
       if (seqsel.conserve != null)
       {
         recalcConservation(); // safer than
@@ -581,7 +584,8 @@ public class SequenceGroup implements AnnotatedCollectionI
 
         ProfilesI info = AAFrequency.calculateHMMProfiles(hmm,
                 (endRes + 1) - startRes, startRes, endRes + 1,
-                showHMMSequenceLogo, ignoreBelowBackground);
+                showHMMSequenceLogo, ignoreBelowBackground,
+                infoLetterHeight);
         _updateInformationRow(info, sequences.size());
         upd = true;
       }
@@ -711,7 +715,7 @@ public class SequenceGroup implements AnnotatedCollectionI
                                                       // width
     information.calcId = "HMM";
     AAFrequency.completeInformation(information, cnsns, startRes,
-            endRes + 1, ignoreBelowBackground, showSequenceLogo, nseq); // TODO:
+            endRes + 1, nseq, 0f); // TODO:
                                                                         // setting
                                                             // container
     // for
@@ -1291,7 +1295,21 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   public boolean getIgnoreBelowBackground()
   {
-    return true;
+    return ignoreBelowBackground;
+  }
+
+  public void setInfoLetterHeight(boolean state)
+  {
+    if (this.infoLetterHeight != state)
+    {
+      infoLetterHeight = state;
+    }
+    infoLetterHeight = state;
+  }
+
+  public boolean getInfoLetterHeight()
+  {
+    return infoLetterHeight;
   }
 
   /**
index f1d8d7c..f7b48fa 100755 (executable)
@@ -624,21 +624,59 @@ public class AnnotationLabels extends JPanel
           @Override
           public void actionPerformed(ActionEvent e)
           {
+
+            if (aaa.groupRef != null)
+            {
+              // TODO: pass on reference to ap so the view can be updated.
+              if (aaa.groupRef.getInfoLetterHeight() == false)
+              {
+                aaa.groupRef.setIgnoreBelowBackground(cbmi.getState());
+                ap.getAnnotationPanel()
+                        .paint(ap.getAnnotationPanel().getGraphics());
+              }
+            }
+            else if (ap.av.isInfoLetterHeight() == false)
+            {
+              ap.av.setIgnoreBelowBackground(cbmi.getState(), ap);
+            }
+            ap.alignmentChanged();
+          }
+        });
+        pop.add(cbmi);
+        final JCheckBoxMenuItem letteHeight = new JCheckBoxMenuItem(
+                MessageManager.getString("label.use_info_for_height"),
+                (aa[selectedRow].groupRef != null)
+                        ? aa[selectedRow].groupRef.getInfoLetterHeight()
+                        : ap.av.isInfoLetterHeight());
+
+        letteHeight.addActionListener(new ActionListener()
+        {
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
             if (aaa.groupRef != null)
             {
               // TODO: pass on reference to ap so the view can be updated.
-              aaa.groupRef.setIgnoreBelowBackground(cbmi.getState());
+              aaa.groupRef.setInfoLetterHeight((letteHeight.getState()));
+              if (aaa.groupRef.getIgnoreBelowBackground() == false)
+              {
+                aaa.groupRef.setIgnoreBelowBackground(true);
+              }
               ap.getAnnotationPanel()
                       .paint(ap.getAnnotationPanel().getGraphics());
             }
             else
             {
-              ap.av.setIgnoreBelowBackground(cbmi.getState(), ap);
+              ap.av.setInfoLetterHeight(letteHeight.getState(), ap);
+              if (ap.av.isIgnoreBelowBackground() == false)
+              {
+                ap.av.setIgnoreBelowBackground(true, ap);
+              }
             }
             ap.alignmentChanged();
           }
         });
-        pop.add(cbmi);
+        pop.add(letteHeight);
         if (aaa.groupRef != null)
         {
           final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
index 6099a85..70d534c 100644 (file)
@@ -75,7 +75,7 @@ public class AnnotationRenderer
           av_normaliseProfile = false;
 
   boolean av_renderInformationHistogram = true, av_renderHMMProfile = true,
-          av_normaliseHMMProfile = false;
+          av_normaliseHMMProfile = false, av_infoHeight = false;
 
   ResidueShaderI profcolour = null;
 
@@ -353,6 +353,7 @@ public class AnnotationRenderer
     hStrucConsensus = av.getRnaStructureConsensusHash();
     av_ignoreGapsConsensus = av.isIgnoreGapsConsensus();
     av_ignoreBelowBackground = av.isIgnoreBelowBackground();
+    av_infoHeight = av.isInfoLetterHeight();
   }
 
 
@@ -376,7 +377,7 @@ public class AnnotationRenderer
     {
       HiddenMarkovModel hmm = aa.sequenceRef.getHMM();
       return AAFrequency.extractHMMProfile(hmm, column,
-              av_ignoreBelowBackground); // TODO check if this follows standard
+              av_ignoreBelowBackground, av_infoHeight); // TODO check if this follows standard
                                          // pipeline
     }
     if (aa.autoCalculated
index ad12035..c2c2c5d 100644 (file)
@@ -616,6 +616,8 @@ public abstract class AlignmentViewport
 
   protected boolean ignoreBelowBackGroundFrequencyCalculation = false;
 
+  protected boolean infoLetterHeight = false;
+
   protected ResidueShaderI residueShading = new ResidueShader();
 
   @Override
@@ -1370,6 +1372,16 @@ public abstract class AlignmentViewport
 
   }
 
+  public void setInfoLetterHeight(boolean b, AlignmentViewPanel ap)
+  {
+    infoLetterHeight = b;
+    if (ap != null)
+    {
+      updateInformation(ap);
+    }
+
+  }
+
   private long sgrouphash = -1, colselhash = -1;
 
   /**
@@ -1430,6 +1442,12 @@ public abstract class AlignmentViewport
     return ignoreBelowBackGroundFrequencyCalculation;
   }
 
+  @Override
+  public boolean isInfoLetterHeight()
+  {
+    return infoLetterHeight;
+  }
+
   // property change stuff
   // JBPNote Prolly only need this in the applet version.
   private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
index 2c92879..2abfc69 100644 (file)
@@ -15,6 +15,9 @@ import java.util.List;
 
 public class InformationThread extends AlignCalcWorker
 {
+  
+  Float max = 0f;
+  
   /**
    * Constructor for information thread.
    * 
@@ -125,11 +128,13 @@ public class InformationThread extends AlignCalcWorker
       int width = alignment.getWidth();
     List<SequenceI> hmmSeqs = alignment.getHMMConsensusSequences(false);
     int index = 0;
+
     for (SequenceI seq : hmmSeqs)
     {
       HiddenMarkovModel hmm = seq.getHMM();
       ProfilesI hinformation = AAFrequency.calculateHMMProfiles(hmm, width,
-              0, width, true, alignViewport.isIgnoreBelowBackground());
+              0, width, true, alignViewport.isIgnoreBelowBackground(),
+              alignViewport.isInfoLetterHeight());
       alignViewport.setSequenceInformationHash(hinformation, index);
       // setColourSchemeInformation(hinformation);
       index++;
@@ -219,12 +224,10 @@ public class InformationThread extends AlignCalcWorker
   protected void deriveInformation(
           AlignmentAnnotation informationAnnotation, ProfilesI hinformation)
     {
-
       long nseq = getSequences().length;
-    AAFrequency.completeInformation(informationAnnotation, hinformation,
-            hinformation.getStartColumn(), hinformation.getEndColumn() + 1,
-            alignViewport.isIgnoreBelowBackground(),
-              alignViewport.isShowHMMSequenceLogo(), nseq);
+    max = AAFrequency.completeInformation(informationAnnotation,
+            hinformation, hinformation.getStartColumn(),
+            hinformation.getEndColumn() + 1, nseq, max);
     }
 
 
index 9a0b33f..05a72e4 100644 (file)
@@ -254,7 +254,7 @@ public class AAFrequencyTest
             "test/jalview/io/test_MADE1_hmm.txt", DataSourceType.FILE));
     hmm = hmmFile.getHMM();
     int[] expected = { 0, 4, 100, 'T', 71, 'C', 12, 'G', 9, 'A', 9 };
-    int[] actual = AAFrequency.extractHMMProfile(hmm, 17, false);
+    int[] actual = AAFrequency.extractHMMProfile(hmm, 17, false, false);
     for (int i = 0; i < actual.length; i++)
     {
       if (i == 2)
@@ -268,7 +268,7 @@ public class AAFrequencyTest
     }
   
     int[] expected2 = { 0, 4, 100, 'A', 85, 'C', 0, 'G', 0, 'T', 0 };
-    int[] actual2 = AAFrequency.extractHMMProfile(hmm, 2, true);
+    int[] actual2 = AAFrequency.extractHMMProfile(hmm, 2, true, false);
     for (int i = 0; i < actual2.length; i++)
     {
       if (i == 2)
@@ -281,18 +281,18 @@ public class AAFrequencyTest
       }
     }
 
-    assertNull(AAFrequency.extractHMMProfile(null, 98978867, true));
+    assertNull(AAFrequency.extractHMMProfile(null, 98978867, true, false));
   }
 
   @Test(groups = { "Functional" }, priority = 2)
   public void testGetAnalogueCount()
   {
     int count;
-    count = AAFrequency.getAnalogueCount(hmm, 0, 'T', false);
+    count = AAFrequency.getAnalogueCount(hmm, 0, 'T', false, false);
     assertEquals(7859, count);
-    count = AAFrequency.getAnalogueCount(hmm, 20, 'G', false);
+    count = AAFrequency.getAnalogueCount(hmm, 20, 'G', false, false);
     assertEquals(7546, count);
-    count = AAFrequency.getAnalogueCount(hmm, 1077, 'G', true);
+    count = AAFrequency.getAnalogueCount(hmm, 1077, 'G', true, false);
     assertEquals(0, count);
   }
 
@@ -310,7 +310,7 @@ public class AAFrequencyTest
     seq.setHMM(hmm);
     AlignmentAnnotation annot = new AlignmentAnnotation("", "", annots);
     annot.setSequenceRef(seq);
-    AAFrequency.completeInformation(annot, profs, 0, 1, false, true, 1);
+    AAFrequency.completeInformation(annot, profs, 0, 1, 1, 1f);
     float ic = annot.annotations[0].value;
     assertEquals(0.91532f, ic, 0.0001f);
     ic = annot.annotations[1].value;