JAL-2599 fix for information annotation buttons
authorTZVanaalten <TZVanaalten@LS30916.ad.lifesci.dundee.ac.uk>
Wed, 2 Aug 2017 09:51:14 +0000 (10:51 +0100)
committerTZVanaalten <TZVanaalten@LS30916.ad.lifesci.dundee.ac.uk>
Wed, 2 Aug 2017 09:51:14 +0000 (10:51 +0100)
15 files changed:
src/jalview/analysis/AAFrequency.java
src/jalview/api/AlignViewportI.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AlignViewport.java
src/jalview/datamodel/AlignmentAnnotation.java
src/jalview/datamodel/HiddenMarkovModel.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AnnotationLabels.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/ResidueShader.java
src/jalview/renderer/ResidueShaderI.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/workers/AlignCalcManager.java

index 900209d..d83f138 100755 (executable)
@@ -110,6 +110,7 @@ public class AAFrequency
   }
 
 
+
   /**
    * Calculate the consensus symbol(s) for each column in the given range.
    * 
@@ -201,6 +202,38 @@ public class AAFrequency
     // System.out.println(elapsed);
   }
 
+  public static ProfilesI calculateInformation(final HiddenMarkovModel hmm,
+          int width, int start, int end, boolean saveFullProfile,
+          boolean removeBelowBackground)
+  {
+    ProfileI[] result = new ProfileI[width];
+    int symbolCount = hmm.getNumberOfSymbols();
+    String alph = hmm.getAlphabetType();
+    for (int column = start; column < end; column++)
+    {
+      ResidueCount counts = new ResidueCount();
+      for (char symbol : hmm.getSymbols())
+      {
+        int value = getAnalogueCount(hmm, column, removeBelowBackground,
+                alph, symbol);
+        counts.put(symbol, value);
+      }
+      int maxCount = counts.getModalCount();
+      String maxResidue = counts.getResiduesForCount(maxCount);
+      int gapCount = counts.getGapCount();
+      ProfileI profile = new Profile(symbolCount, gapCount, maxCount,
+              maxResidue);
+
+      if (saveFullProfile)
+      {
+        profile.setCounts(counts);
+      }
+
+      result[column] = profile;
+    }
+    return new Profiles(result);
+  }
+
   /**
    * Make an estimate of the profile size we are going to compute i.e. how many
    * different characters may be present in it. Overestimating has a cost of
@@ -299,6 +332,82 @@ public class AAFrequency
   }
 
   /**
+   * Derive the information annotations to be added to the alignment for
+   * display. This does not recompute the raw data, but may be called on a
+   * change in display options, such as 'ignore below background frequency',
+   * which may in turn result in a change in the derived values.
+   * 
+   * @param information
+   *          the annotation row to add annotations to
+   * @param profiles
+   *          the source information data
+   * @param startCol
+   *          start column (inclusive)
+   * @param endCol
+   *          end column (exclusive)
+   * @param ignoreGaps
+   *          if true, normalise residue percentages 
+   * @param showSequenceLogo
+   *          if true include all information symbols, else just show modal
+   *          residue
+   * @param nseq
+   *          number of sequences
+   */
+  public static void completeInformation(AlignmentAnnotation information,
+          ProfilesI profiles, int startCol, int endCol,
+          boolean ignoreBelowBackground,
+          boolean showSequenceLogo, long nseq)
+  {
+    // long now = System.currentTimeMillis();
+    if (information == null || information.annotations == null
+            || information.annotations.length < endCol)
+    {
+      /*
+       * called with a bad alignment annotation row 
+       * wait for it to be initialised properly
+       */
+      return;
+    }
+
+    Float max = 0f;
+
+    for (int i = startCol; i < endCol; i++)
+    {
+      ProfileI profile = profiles.get(i);
+      if (profile == null)
+      {
+        /*
+         * happens if sequences calculated over were 
+         * shorter than alignment width
+         */
+        information.annotations[i] = null;
+        return;
+      }
+
+      HiddenMarkovModel hmm;
+      
+      SequenceI hmmSeq = information.sequenceRef;
+      
+      hmm = hmmSeq.getHMM();
+      
+      Float value = getInformationContent(i, hmm);
+
+      if (value > max)
+      {
+        max = value;
+      }
+
+      String description = value + " bits";
+      
+      information.annotations[i] = new Annotation(" ", description,
+              ' ', value);
+    }
+    information.graphMax = max;
+    // long elapsed = System.currentTimeMillis() - now;
+    // System.out.println(-elapsed);
+  }
+
+  /**
    * Derive the gap count annotation row.
    * 
    * @param gaprow
@@ -730,6 +839,42 @@ public class AAFrequency
   }
 
   /**
+   * Returns the information content at a specified column.
+   * 
+   * @param column
+   *          Index of the column, starting from 0.
+   * @return
+   */
+  public static float getInformationContent(int column,
+          HiddenMarkovModel hmm)
+  {
+    float informationContent = 0f;
+
+    for (char symbol : hmm.getSymbols())
+    {
+      float freq = 0f;
+      if ("amino".equals(hmm.getAlphabetType()))
+      {
+        freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol);
+      }
+      if ("DNA".equals(hmm.getAlphabetType()))
+      {
+        freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol);
+      }
+      if ("RNA".equals(hmm.getAlphabetType()))
+      {
+        freq = ResidueProperties.rnaBackgroundFrequencies.get(symbol);
+      }
+      Double hmmProb = hmm.getMatchEmissionProbability(column, symbol);
+      float prob = hmmProb.floatValue();
+      informationContent += prob * (Math.log(prob / freq) / Math.log(2));
+
+    }
+
+    return informationContent;
+  }
+
+  /**
    * Produces a HMM profile for a column in an alignment
    * 
    * @param aa
@@ -741,7 +886,7 @@ public class AAFrequency
    *          less than their background frequencies.
    * @return
    */
-  public static int[] getHMMProfileFor(HiddenMarkovModel hmm, int column,
+  public static int[] extractHMMProfile(HiddenMarkovModel hmm, int column,
           boolean removeBelowBackground)
   {
 
@@ -758,39 +903,10 @@ public class AAFrequency
       {
         char symbol = charList.get(i);
         symbols[i] = symbol;
-        Double value;
-
-        value = hmm.getMatchEmissionProbability(column, symbol);
-        double freq;
-
-        if (AMINO.equals(alph) && removeBelowBackground)
-        {
-          freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol);
-          if (value < freq)
-          {
-            value = 0d;
-          }
-        }
-        else if (DNA.equals(alph) && removeBelowBackground)
-        {
-          freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol);
-          if (value < freq)
-          {
-            value = 0d;
-          }
-        }
-        else if (RNA.equals(alph) && removeBelowBackground)
-        {
-          freq = ResidueProperties.rnaBackgroundFrequencies
-                  .get(symbol);
-          if (value < freq)
-          {
-            value = 0d;
-          }
-        }
-        value = value * 10000;
-        values[i] = value.intValue();
-        totalCount += value.intValue();
+        int value = getAnalogueCount(hmm, column, removeBelowBackground,
+                alph, symbol);
+        values[i] = value;
+        totalCount += value;
       }
 
       QuickSort.sort(values, symbols);
@@ -819,4 +935,40 @@ public class AAFrequency
     }
     return null;
   }
+
+  private static int getAnalogueCount(HiddenMarkovModel hmm, int column,
+          boolean removeBelowBackground, String alph, char symbol)
+  {
+    Double value;
+
+    value = hmm.getMatchEmissionProbability(column, symbol);
+    double freq;
+
+    if (AMINO.equals(alph) && removeBelowBackground)
+    {
+      freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol);
+      if (value < freq)
+      {
+        value = 0d;
+      }
+    }
+    else if (DNA.equals(alph) && removeBelowBackground)
+    {
+      freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol);
+      if (value < freq)
+      {
+        value = 0d;
+      }
+    }
+    else if (RNA.equals(alph) && removeBelowBackground)
+    {
+      freq = ResidueProperties.rnaBackgroundFrequencies.get(symbol);
+      if (value < freq)
+      {
+        value = 0d;
+      }
+    }
+    value = value * 10000;
+    return value.intValue();
+  }
 }
index 6ebde3c..4b6dc4e 100644 (file)
@@ -108,6 +108,8 @@ public interface AlignViewportI extends ViewStyleI
 
   ProfilesI getSequenceConsensusHash();
 
+  ProfilesI getSequenceInformationHash();
+
   /**
    * Get consensus data table for the cDNA complement of this alignment (if any)
    * 
@@ -188,6 +190,13 @@ public interface AlignViewportI extends ViewStyleI
   void setSequenceConsensusHash(ProfilesI hconsensus);
 
   /**
+   * set the information result object for the viewport
+   * 
+   * @param hconsensus
+   */
+  void setSequenceInformationHash(ProfilesI hinformation);
+
+  /**
    * Set the cDNA complement consensus for the viewport
    * 
    * @param hconsensus
@@ -511,4 +520,6 @@ public interface AlignViewportI extends ViewStyleI
    */
   @Override
   void setProteinFontAsCdna(boolean b);
+
+  ProfilesI setSequenceInformationHash();
 }
index 02d30bb..f764be6 100644 (file)
@@ -234,6 +234,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             alignPanel);
     viewport.updateConservation(alignPanel);
     viewport.updateConsensus(alignPanel);
+    viewport.updateInformation(alignPanel);
 
     displayNonconservedMenuItem.setState(viewport.getShowUnconserved());
     followMouseOverFlag.setState(viewport.isFollowHighlight());
index 6c7b39a..99059cf 100644 (file)
@@ -28,6 +28,7 @@ import jalview.commands.CommandI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
@@ -476,4 +477,18 @@ public class AlignViewport extends AlignmentViewport implements
     return normaliseHMMSequenceLogo;
   }
 
+  @Override
+  public ProfilesI getSequenceInformationHash()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public void setSequenceInformationHash(ProfilesI hinformation)
+  {
+    // TODO Auto-generated method stub
+
+  }
+
 }
index e8e8d01..8f826f5 100755 (executable)
@@ -51,8 +51,6 @@ public class AlignmentAnnotation
 
   public static final int CDNA_PROFILE = 2;
 
-  HiddenMarkovModel hmm;
-
   private static long counter = 0;
 
   /**
@@ -1506,13 +1504,4 @@ public class AlignmentAnnotation
     return graphMin < graphMax;
   }
 
-  public void setHMM(HiddenMarkovModel markov)
-  {
-    hmm = markov;
-  }
-
-  public HiddenMarkovModel getHMM()
-  {
-    return hmm;
-  }
 }
index e0f13d8..2c1632d 100644 (file)
@@ -1,7 +1,6 @@
 package jalview.datamodel;
 
 import jalview.gui.AlignFrame;
-import jalview.schemes.ResidueProperties;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -973,81 +972,7 @@ public class HiddenMarkovModel
     }
   }
 
-  /**
-   * Creates the HMM Logo alignment annotation, and populates it with
-   * information content data.
-   * 
-   * @return The alignment annotation.
-   */
-  public AlignmentAnnotation createAnnotation(int length)
-  {
-    Annotation[] annotations = new Annotation[length];
-    float max = 0f;
-    for (int alignPos = 0; alignPos < length; alignPos++)
-    {
-      Float content = getInformationContent(alignPos);
-      if (content > max)
-      {
-        max = content;
-      }
-
-      Character cons;
-
-      cons = getConsensusAtAlignColumn(alignPos);
-
-      cons = Character.toUpperCase(cons);
-
-      String description = String.format("%.3f", content);
-      description += " bits";
-      annotations[alignPos] = new Annotation(cons.toString(), description,
-              ' ',
-              content);
-
-    }
-    AlignmentAnnotation annotation = new AlignmentAnnotation(
-            "Information",
-            "The information content of each column, measured in bits",
-            annotations,
-            0f, max, AlignmentAnnotation.BAR_GRAPH);
-    annotation.setHMM(this);
-    return annotation;
-  }
-
-  /**
-   * Returns the information content at a specified column.
-   * 
-   * @param column
-   *          Index of the column, starting from 0.
-   * @return
-   */
-  public float getInformationContent(int column)
-  {
-    float informationContent = 0f;
 
-    for (char symbol : symbols)
-    {
-      float freq = 0f;
-      if ("amino".equals(getAlphabetType()))
-      {
-        freq = ResidueProperties.aminoBackgroundFrequencies.get(symbol);
-      }
-      if ("DNA".equals(getAlphabetType()))
-      {
-        freq = ResidueProperties.dnaBackgroundFrequencies.get(symbol);
-      }
-      if ("RNA".equals(getAlphabetType()))
-      {
-        freq = ResidueProperties.rnaBackgroundFrequencies
-                .get(symbol);
-      }
-      Double hmmProb = getMatchEmissionProbability(column, symbol);
-      float prob = hmmProb.floatValue();
-      informationContent += prob * (Math.log(prob / freq) / Math.log(2));
-
-    }
-
-    return informationContent;
-  }
 
   /**
    * Returns the consensus sequence based on the most probable symbol at each
@@ -1112,6 +1037,12 @@ public class HiddenMarkovModel
       return;
     }
 
+    mapToReferenceAnnotation(reference);
+    af.getViewport().getAlignment().deleteAnnotation(reference);
+  }
+
+  public void mapToReferenceAnnotation(AlignmentAnnotation reference)
+  {
     Annotation[] annots = reference.annotations;
     {
       int nodeIndex = 0;
@@ -1140,10 +1071,10 @@ public class HiddenMarkovModel
       }
 
     }
-    af.getViewport().getAlignment().deleteAnnotation(reference);
+
   }
 
-  public void initPlaceholder(AlignFrame af)
+  public SequenceI initPlaceholder(AlignFrame af)
   {
     AlignmentI alignment = af.getViewport().getAlignment();
     int length = alignment.getWidth();
@@ -1153,6 +1084,7 @@ public class HiddenMarkovModel
     AlignmentI newAlignment = new Alignment(consensusArr);
     newAlignment.append(alignment);
     af.getViewport().setAlignment(newAlignment);
+    return consensus;
   }
 
 }
index 39ee2cb..eeff135 100755 (executable)
@@ -128,7 +128,7 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   AlignmentAnnotation conservation = null;
 
-  AlignmentAnnotation informationContent = null;
+  AlignmentAnnotation information = null;
 
   private boolean showConsensusHistogram;
 
@@ -565,7 +565,7 @@ public class SequenceGroup implements AnnotatedCollectionI
   public boolean recalcConservation(boolean defer)
   {
     if (cs == null && consensus == null && conservation == null
-            && informationContent == null)
+            && information == null)
     {
       return false;
     }
@@ -576,7 +576,7 @@ public class SequenceGroup implements AnnotatedCollectionI
     {
       ProfilesI cnsns = AAFrequency.calculate(sequences, startRes,
               endRes + 1, showSequenceLogo);
-      if (informationContent != null)
+      if (information != null)
       {
         // _updateInformationRow(cnsns, sequences.size()); TODO don't know what
         // to do here
@@ -654,6 +654,8 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   public ProfilesI consensusData = null;
 
+  public ProfilesI informationData = null;
+
   private void _updateConsensusRow(ProfilesI cnsns, long nseq)
   {
     if (consensus == null)
@@ -679,26 +681,28 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   private void _updateInformationRow(ProfilesI cnsns, long nseq)
   {
-    if (consensus == null)
+    if (information == null)
     {
-      getConsensus();
+      getInformation();
     }
-    consensus.label = "Consensus for " + getName();
-    consensus.description = "Percent Identity";
-    consensusData = cnsns;
+    information.label = "Information for " + getName();
+    information.description = "Percent Identity";
+    informationData = cnsns;
     // preserve width if already set
-    int aWidth = (consensus.annotations != null)
-            ? (endRes < consensus.annotations.length
-                    ? consensus.annotations.length : endRes + 1)
+    int aWidth = (information.annotations != null)
+            ? (endRes < information.annotations.length
+                    ? information.annotations.length : endRes + 1)
             : endRes + 1;
-    consensus.annotations = null;
-    consensus.annotations = new Annotation[aWidth]; // should be alignment width
+    information.annotations = null;
+    information.annotations = new Annotation[aWidth]; // should be alignment
+                                                      // width
 
-    AAFrequency.completeConsensus(consensus, cnsns, startRes, endRes + 1,
-            ignoreGapsInConsensus, showSequenceLogo, nseq); // TODO: setting
+    AAFrequency.completeInformation(information, cnsns, startRes,
+            endRes + 1, ignoreBelowBackground, showSequenceLogo, nseq); // TODO:
+                                                                        // setting
                                                             // container
     // for
-    // ignoreGapsInConsensusCalculation);
+    // ignoreGapsInInformationCalculation);
   }
 
   /**
@@ -1149,6 +1153,34 @@ public class SequenceGroup implements AnnotatedCollectionI
   }
 
   /**
+   * 
+   * @return information content annotation.
+   */
+  public AlignmentAnnotation getInformation()
+  {
+    // TODO get or calculate and get information annotation row for this group
+    int aWidth = this.getWidth();
+    // pointer
+    // possibility
+    // here.
+    if (aWidth < 0)
+    {
+      return null;
+    }
+    if (information == null)
+    {
+      information = new AlignmentAnnotation("", "", new Annotation[1], 0f,
+              100f, AlignmentAnnotation.BAR_GRAPH);
+      information.hasText = true;
+      information.autoCalculated = true;
+      information.groupRef = this;
+      information.label = "Consensus for " + getName();
+      information.description = "Percent Identity";
+    }
+    return information;
+  }
+
+  /**
    * set this alignmentAnnotation object as the one used to render consensus
    * annotation
    * 
@@ -1526,7 +1558,7 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   public void setShowInformationHistogram(boolean state)
   {
-    if (showInformationHistogram != state && informationContent != null)
+    if (showInformationHistogram != state && information != null)
     {
       this.showInformationHistogram = state;
       // recalcConservation(); TODO don't know what to do here next
index 6dccadc..2168bd1 100644 (file)
@@ -92,6 +92,7 @@ import jalview.schemes.TCoffeeColourScheme;
 import jalview.util.MessageManager;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.ViewportRanges;
+import jalview.workers.InformationThread;
 import jalview.ws.DBRefFetcher;
 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
 import jalview.ws.jws1.Discoverer;
@@ -800,6 +801,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       ap.av.updateConservation(ap);
       ap.av.updateConsensus(ap);
       ap.av.updateStrucConsensus(ap);
+      ap.av.updateInformation(ap);
     }
   }
 
@@ -4712,12 +4714,13 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
             HiddenMarkovModel hmm = hmmFile.getHMM();
 
             hmm.mapToReferenceAnnotation(this);
+            SequenceI hmmSeq = hmm.initPlaceholder(this);
+            getViewport().initInformation(hmmSeq);
+            new Thread(new InformationThread(getViewport(),
+                    getViewport().getAlignPanel())
+            {
+            }).start();
 
-
-            AlignmentAnnotation annotation = hmm.createAnnotation(
-                    getViewport().getAlignment().getWidth());
-            getViewport().getAlignment().addAnnotation(annotation);
-            hmm.initPlaceholder(this);
             isAnnotation = true;
             alignPanel.repaint();
 
index 2005b91..f4ded5b 100644 (file)
@@ -37,6 +37,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
@@ -703,6 +704,7 @@ public class AlignViewport extends AlignmentViewport implements
     return normaliseSequenceLogo;
   }
 
+
   public void setNormaliseSequenceLogo(boolean state)
   {
     normaliseSequenceLogo = state;
@@ -1157,8 +1159,20 @@ public class AlignViewport extends AlignmentViewport implements
   @Override
   public boolean isNormaliseHMMSequenceLogo()
   {
-    // TODO Auto-generated method stub
     return normaliseHMMSequenceLogo;
   }
 
+  @Override
+  public ProfilesI getSequenceInformationHash()
+  {
+    return hinformation;
+  }
+
+  @Override
+  public void setSequenceInformationHash(ProfilesI hinformation)
+  {
+    this.hinformation = hinformation;
+
+  }
+
 }
index 1834fc2..090a400 100755 (executable)
@@ -554,7 +554,6 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               // can be
               // updated.
               av.setShowConsensusHistogram(chist.getState());
-              ap.alignFrame.setMenusForViewport();
               ap.repaint();
               // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
             }
@@ -575,7 +574,6 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               // can be
               // updated.
               av.setShowSequenceLogo(cprof.getState());
-              ap.alignFrame.setMenusForViewport();
               ap.repaint();
               // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
             }
@@ -597,7 +595,6 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               // updated.
               av.setShowSequenceLogo(true);
               av.setNormaliseSequenceLogo(cprofnorm.getState());
-              ap.alignFrame.setMenusForViewport();
               ap.repaint();
               // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
             }
@@ -727,7 +724,6 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               // can be
               // updated.
               av.setShowInformationHistogram(chist.getState());
-              ap.alignFrame.setMenusForViewport();
               ap.repaint();
               // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
             }
@@ -747,8 +743,8 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               // view
               // can be
               // updated.
+              av.updateInformation(ap);
               av.setShowHMMSequenceLogo(cprof.getState());
-              ap.alignFrame.setMenusForViewport();
               ap.repaint();
               // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
             }
@@ -770,16 +766,12 @@ public class AnnotationLabels extends JPanel implements MouseListener,
               // updated.
               av.setShowHMMSequenceLogo(true);
               av.setNormaliseHMMSequenceLogo(cprofnorm.getState());
-              ap.alignFrame.setMenusForViewport();
               ap.repaint();
               // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
             }
           });
           pop.add(cprofnorm);
         }
-        final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ);
-        consclipbrd.addActionListener(this);
-        pop.add(consclipbrd);
       }
     }
     pop.show(this, evt.getX(), evt.getY());
index 78b3a88..9aec02c 100644 (file)
@@ -74,6 +74,9 @@ public class AnnotationRenderer
   boolean av_renderHistogram = true, av_renderProfile = true,
           av_normaliseProfile = false;
 
+  boolean av_renderInformationHistogram = true, av_renderHMMProfile = true,
+          av_normaliseHMMProfile = false;
+
   ResidueShaderI profcolour = null;
 
   private ColumnSelection columnSelection;
@@ -320,6 +323,9 @@ public class AnnotationRenderer
     av_renderHistogram = av.isShowConsensusHistogram();
     av_renderProfile = av.isShowSequenceLogo();
     av_normaliseProfile = av.isNormaliseSequenceLogo();
+    av_renderInformationHistogram = av.isShowInformationHistogram();
+    av_renderHMMProfile = av.isShowHMMSequenceLogo();
+    av_normaliseHMMProfile = av.isNormaliseHMMSequenceLogo();
     profcolour = av.getResidueShading();
     if (profcolour == null || profcolour.getColourScheme() == null)
     {
@@ -360,8 +366,8 @@ public class AnnotationRenderer
     //
     if (aa.label.startsWith("Information"))
     {
-      HiddenMarkovModel hmm = aa.getHMM();
-      return AAFrequency.getHMMProfileFor(hmm, column,
+      HiddenMarkovModel hmm = aa.sequenceRef.getHMM();
+      return AAFrequency.extractHMMProfile(hmm, column,
               av_ignoreBelowBackground); // TODO check if this follows standard
                                          // pipeline
     }
@@ -472,6 +478,8 @@ hconsensus.get(column),
     boolean scaleColLabel = false;
     final AlignmentAnnotation consensusAnnot = av
             .getAlignmentConsensusAnnotation();
+    final AlignmentAnnotation informationAnnot = av
+            .getAlignmentInformationAnnotation();
     final AlignmentAnnotation structConsensusAnnot = av
             .getAlignmentStrucConsensusAnnotation();
     final AlignmentAnnotation complementConsensusAnnot = av
@@ -509,6 +517,12 @@ hconsensus.get(column),
           renderProfile = av_renderProfile;
           normaliseProfile = av_normaliseProfile;
         }
+        else if (row == informationAnnot)
+        {
+          renderHistogram = av_renderInformationHistogram;
+          renderProfile = av_renderHMMProfile;
+          normaliseProfile = av_normaliseHMMProfile;
+        }
         else
         {
           renderHistogram = true;
index b6f7fe6..3a94b4f 100644 (file)
@@ -372,4 +372,11 @@ public class ResidueShader implements ResidueShaderI
   {
     colourScheme = cs;
   }
+
+  @Override
+  public void setInformation(ProfilesI info)
+  {
+    // TODO Auto-generated method stub
+
+  }
 }
index a914a1a..d85c70c 100644 (file)
@@ -15,6 +15,8 @@ public interface ResidueShaderI
 
   public abstract void setConsensus(ProfilesI cons);
 
+  public abstract void setInformation(ProfilesI info);
+
   public abstract boolean conservationApplied();
 
   public abstract void setConservationApplied(boolean conservationApplied);
index 61b0b00..91caebc 100644 (file)
@@ -57,6 +57,7 @@ import jalview.viewmodel.styles.ViewStyle;
 import jalview.workers.AlignCalcManager;
 import jalview.workers.ComplementConsensusThread;
 import jalview.workers.ConsensusThread;
+import jalview.workers.InformationThread;
 import jalview.workers.StrucConsensusThread;
 
 import java.awt.Color;
@@ -606,6 +607,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   public boolean autoCalculateConsensus = true;
 
+  public boolean autoCalculateInformation = true;
+
   protected boolean autoCalculateStrucConsensus = true;
 
   protected boolean ignoreGapsInConsensusCalculation = false;
@@ -699,7 +702,14 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   protected AlignmentAnnotation[] groupConservation;
 
-  protected AlignmentAnnotation informationContent;
+  protected AlignmentAnnotation[] groupInformation;
+
+  protected AlignmentAnnotation information;
+
+  /**
+   * results of alignment information analysis for visible portion of view
+   */
+  protected ProfilesI hinformation = null;
 
   /**
    * results of alignment consensus analysis for visible portion of view
@@ -756,6 +766,18 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
+  public ProfilesI setSequenceInformationHash()
+  {
+    return hinformation;
+  }
+
+  @Override
+  public ProfilesI getSequenceInformationHash()
+  {
+    return hinformation;
+  }
+
+  @Override
   public Hashtable[] getComplementConsensusHash()
   {
     return hcomplementConsensus;
@@ -795,7 +817,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   @Override
   public AlignmentAnnotation getAlignmentInformationAnnotation()
   {
-    return informationContent;
+    return information;
   }
 
   @Override
@@ -889,6 +911,23 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
   }
 
+  /**
+   * trigger update of information annotation
+   */
+  public void updateInformation(final AlignmentViewPanel ap)
+  {
+    if (information == null)
+    {
+      return;
+    }
+    if (calculator
+            .getRegisteredWorkersOfClass(InformationThread.class) == null)
+    {
+      calculator.registerWorker(new InformationThread(this, ap));
+    }
+
+  }
+
   // --------START Structure Conservation
   public void updateStrucConsensus(final AlignmentViewPanel ap)
   {
@@ -946,6 +985,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
      * defensively null out references to large objects in case
      * this object is not garbage collected (as if!)
      */
+    information = null;
     consensus = null;
     complementConsensus = null;
     strucConsensus = null;
@@ -1057,6 +1097,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
     if (showHMMSequenceLogo != this.showHMMSequenceLogo)
     {
       this.showHMMSequenceLogo = showHMMSequenceLogo;
+      calculator.updateAnnotationFor(InformationThread.class);
     }
     this.showHMMSequenceLogo = showHMMSequenceLogo;
   }
@@ -1299,12 +1340,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
     ignoreBelowBackGroundFrequencyCalculation = b;
     if (ap != null)
     {
-      // updateConsensus(ap);
-      if (residueShading != null)
-      {
-        residueShading.setThreshold(residueShading.getThreshold(),
-                ignoreBelowBackGroundFrequencyCalculation);
-      }
+      updateInformation(ap);
     }
 
   }
@@ -1923,6 +1959,10 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       updateStrucConsensus(ap);
     }
+    if (information != null)
+    {
+      updateInformation(ap);
+    }
 
     // Reset endRes of groups if beyond alignment width
     int alWidth = alignment.getWidth();
@@ -1959,6 +1999,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
       rs.alignmentChanged(alignment, hiddenRepSequences);
 
       rs.setConsensus(hconsensus);
+      rs.setInformation(hinformation);
       if (rs.conservationApplied())
       {
         rs.setConservation(Conservation.calculateConservation("All",
@@ -2005,6 +2046,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
   }
 
+
   /**
    * If this is a protein alignment and there are mappings to cDNA, adds the
    * cDNA consensus annotation and returns true, else returns false.
@@ -2056,6 +2098,19 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
   }
 
+  public void initInformation(SequenceI hmmSequence)
+  {
+    information = new AlignmentAnnotation("Information",
+            MessageManager.getString("label.information_description"),
+            new Annotation[1], 0f, 6.52f, AlignmentAnnotation.BAR_GRAPH);
+    information.hasText = true;
+    information.autoCalculated = true;
+    information.hasText = true;
+    information.autoCalculated = false;
+    information.sequenceRef = hmmSequence;
+    alignment.addAnnotation(information);
+  }
+
   // these should be extracted from the view model - style and settings for
   // derived annotation
   private void initGapCounts()
@@ -2205,6 +2260,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
     boolean showprf = isShowSequenceLogo();
     boolean showConsHist = isShowConsensusHistogram();
     boolean normLogo = isNormaliseSequenceLogo();
+    boolean showHMMPrf = isShowHMMSequenceLogo();
+    boolean showInfoHist = isShowInformationHistogram();
+    boolean normHMMLogo = isNormaliseHMMSequenceLogo();
 
     /**
      * TODO reorder the annotation rows according to group/sequence ordering on
@@ -2242,6 +2300,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
           sg.setshowSequenceLogo(showprf);
           sg.setShowConsensusHistogram(showConsHist);
           sg.setNormaliseSequenceLogo(normLogo);
+          sg.setshowHMMSequenceLogo(showHMMPrf);
+          sg.setShowInformationHistogram(showInfoHist);
+          sg.setNormaliseHMMSequenceLogo(normHMMLogo);
         }
         if (conv)
         {
index addb372..d52ffe5 100644 (file)
@@ -74,7 +74,7 @@ public class AlignCalcManager implements AlignCalcManagerI
             .synchronizedList(new ArrayList<AlignCalcWorkerI>());
     updating = Collections
             .synchronizedMap(new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
-    canUpdate = new HashSet<AlignCalcWorkerI>();
+    canUpdate = new HashSet<>();
   }
 
   @Override
@@ -286,7 +286,7 @@ public class AlignCalcManager implements AlignCalcManagerI
   public List<AlignCalcWorkerI> getRegisteredWorkersOfClass(
           Class<? extends AlignCalcWorkerI> workerClass)
   {
-    List<AlignCalcWorkerI> workingClass = new ArrayList<AlignCalcWorkerI>();
+    List<AlignCalcWorkerI> workingClass = new ArrayList<>();
     synchronized (canUpdate)
     {
       for (AlignCalcWorkerI worker : canUpdate)
@@ -313,8 +313,8 @@ public class AlignCalcManager implements AlignCalcManagerI
   public void removeRegisteredWorkersOfClass(
           Class<? extends AlignCalcWorkerI> typeToRemove)
   {
-    List<AlignCalcWorkerI> removable = new ArrayList<AlignCalcWorkerI>();
-    Set<AlignCalcWorkerI> toremovannot = new HashSet<AlignCalcWorkerI>();
+    List<AlignCalcWorkerI> removable = new ArrayList<>();
+    Set<AlignCalcWorkerI> toremovannot = new HashSet<>();
     synchronized (restartable)
     {
       for (AlignCalcWorkerI worker : restartable)
@@ -364,7 +364,7 @@ public class AlignCalcManager implements AlignCalcManagerI
      * first just find those to remove (to avoid
      * ConcurrentModificationException)
      */
-    List<AlignCalcWorkerI> toRemove = new ArrayList<AlignCalcWorkerI>();
+    List<AlignCalcWorkerI> toRemove = new ArrayList<>();
     for (AlignCalcWorkerI worker : restartable)
     {
       if (worker.involves(ann))