JAL-2629 revising hmmer annotation updating (wip)
[jalview.git] / src / jalview / viewmodel / AlignmentViewport.java
index 107cdd4..ecca699 100644 (file)
@@ -22,6 +22,7 @@ package jalview.viewmodel;
 
 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.analysis.Conservation;
+import jalview.analysis.TreeModel;
 import jalview.api.AlignCalcManagerI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
@@ -33,10 +34,11 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.Annotation;
-import jalview.datamodel.CigarArray;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.HiddenSequences;
+import jalview.datamodel.ProfileI;
+import jalview.datamodel.Profiles;
 import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
@@ -57,6 +59,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;
@@ -77,10 +80,10 @@ import java.util.Map;
  * @author jimp
  * 
  */
-public abstract class AlignmentViewport implements AlignViewportI,
-        CommandListener, VamsasSource
+public abstract class AlignmentViewport
+        implements AlignViewportI, CommandListener, VamsasSource
 {
-  final protected ViewportRanges ranges;
+  protected ViewportRanges ranges;
 
   protected ViewStyleI viewStyle = new ViewStyle();
 
@@ -96,10 +99,73 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   protected Deque<CommandI> redoList = new ArrayDeque<>();
 
+  protected String sequenceSetID;
+
+  /*
+   * probably unused indicator that view is of a dataset rather than an
+   * alignment
+   */
+  protected boolean isDataset = false;
+
+  private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
+
+  protected ColumnSelection colSel = new ColumnSelection();
+
+  public boolean autoCalculateConsensus = true;
+
+  public boolean autoCalculateInformation = true;
+
+  protected boolean autoCalculateStrucConsensus = true;
+
+  protected boolean ignoreGapsInConsensusCalculation = false;
+
+  protected boolean ignoreBelowBackGroundFrequencyCalculation = false;
+
+  protected boolean infoLetterHeight = false;
+
+  protected ResidueShaderI residueShading = new ResidueShader();
+
+  protected AlignmentAnnotation consensus;
+
+  protected AlignmentAnnotation complementConsensus;
+
+  protected AlignmentAnnotation occupancy;
+
+  protected AlignmentAnnotation strucConsensus;
+
+  protected AlignmentAnnotation conservation;
+
+  protected AlignmentAnnotation quality;
+
+  protected List<AlignmentAnnotation> information = new ArrayList<>();
+
+  /**
+   * alignment displayed in the viewport
+   */
+  private AlignmentI alignment;
+
+  /**
+   * results of alignment consensus analysis for visible portion of view
+   */
+  protected ProfilesI hconsensus = null;
+
   /**
-   * alignment displayed in the viewport. Please use get/setter
+   * results of information annotation analysis for the visible portion of view
    */
-  protected AlignmentI alignment;
+  protected List<ProfilesI> hinformation = new ArrayList<>();
+
+  /**
+   * results of cDNA complement consensus visible portion of view
+   */
+  protected Hashtable[] hcomplementConsensus = null;
+
+  /**
+   * results of secondary structure base pair consensus for visible portion of
+   * view
+   */
+  protected Hashtable[] hStrucConsensus = null;
+
+  protected Conservation hconservation = null;
 
   public AlignmentViewport(AlignmentI al)
   {
@@ -405,6 +471,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   public void setWrapAlignment(boolean state)
   {
     viewStyle.setWrapAlignment(state);
+    ranges.setWrappedMode(state);
   }
 
   /**
@@ -567,8 +634,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     viewStyle.setSeqNameItalics(default1);
   }
 
-
-
   @Override
   public AlignmentI getAlignment()
   {
@@ -581,14 +646,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return alignment.getGapCharacter();
   }
 
-  protected String sequenceSetID;
-
-  /**
-   * probably unused indicator that view is of a dataset rather than an
-   * alignment
-   */
-  protected boolean isDataset = false;
-
   public void setDataset(boolean b)
   {
     isDataset = b;
@@ -599,18 +656,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return isDataset;
   }
 
-  private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
-
-  protected ColumnSelection colSel = new ColumnSelection();
-
-  public boolean autoCalculateConsensus = true;
-
-  protected boolean autoCalculateStrucConsensus = true;
-
-  protected boolean ignoreGapsInConsensusCalculation = false;
-
-  protected ResidueShaderI residueShading = new ResidueShader();
-
   @Override
   public void setGlobalColourScheme(ColourSchemeI cs)
   {
@@ -642,6 +687,11 @@ public abstract class AlignmentViewport implements AlignViewportI,
       {
         residueShading.setConservation(hconservation);
       }
+      /*
+       * reset conservation flag in case just set to false if
+       * Conservation was null (calculation still in progress)
+       */
+      residueShading.setConservationApplied(getConservationSelected());
       residueShading.alignmentChanged(alignment, hiddenRepSequences);
     }
 
@@ -660,8 +710,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
         sg.setColourScheme(cs);
         if (cs != null)
         {
-          sg.getGroupColourScheme()
-                  .alignmentChanged(sg, hiddenRepSequences);
+          sg.getGroupColourScheme().alignmentChanged(sg,
+                  hiddenRepSequences);
         }
       }
     }
@@ -670,8 +720,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
   @Override
   public ColourSchemeI getGlobalColourScheme()
   {
-    return residueShading == null ? null : residueShading
-            .getColourScheme();
+    return residueShading == null ? null : residueShading.getColourScheme();
   }
 
   @Override
@@ -679,41 +728,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
   {
     return residueShading;
   }
-
-  protected AlignmentAnnotation consensus;
-
-  protected AlignmentAnnotation complementConsensus;
-
-  protected AlignmentAnnotation gapcounts;
-
-  protected AlignmentAnnotation strucConsensus;
-
-  protected AlignmentAnnotation conservation;
-
-  protected AlignmentAnnotation quality;
-
-  protected AlignmentAnnotation[] groupConsensus;
-
-  protected AlignmentAnnotation[] groupConservation;
-
-  /**
-   * results of alignment consensus analysis for visible portion of view
-   */
-  protected ProfilesI hconsensus = null;
-
-  /**
-   * results of cDNA complement consensus visible portion of view
-   */
-  protected Hashtable[] hcomplementConsensus = null;
-
-  /**
-   * results of secondary structure base pair consensus for visible portion of
-   * view
-   */
-  protected Hashtable[] hStrucConsensus = null;
-
-  protected Conservation hconservation = null;
-
   @Override
   public void setConservation(Conservation cons)
   {
@@ -751,6 +765,34 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
+  public void setSequenceInformationHashes(List<ProfilesI> info)
+  {
+    hinformation = info;
+  }
+
+  @Override
+  public void setSequenceInformationHash(ProfilesI info, int index)
+  {
+    if (hinformation.size() < index + 1)
+    {
+      return;
+    }
+    hinformation.set(index, info);
+  }
+
+  @Override
+  public List<ProfilesI> getSequenceInformationHashes()
+  {
+    return hinformation;
+  }
+
+  @Override
+  public ProfilesI getSequenceInformationHash(int index)
+  {
+    return hinformation.get(index);
+  }
+
+  @Override
   public Hashtable[] getComplementConsensusHash()
   {
     return hcomplementConsensus;
@@ -788,9 +830,15 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
+  public List<AlignmentAnnotation> getInformationAnnotations()
+  {
+    return information;
+  }
+
+  @Override
   public AlignmentAnnotation getAlignmentGapAnnotation()
   {
-    return gapcounts;
+    return occupancy;
   }
 
   @Override
@@ -819,11 +867,11 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       return;
     }
-    if (calculator
-            .getRegisteredWorkersOfClass(jalview.workers.ConservationThread.class) == null)
+    if (calculator.getRegisteredWorkersOfClass(
+            jalview.workers.ConservationThread.class) == null)
     {
-      calculator.registerWorker(new jalview.workers.ConservationThread(
-              this, ap));
+      calculator.registerWorker(
+              new jalview.workers.ConservationThread(this, ap));
     }
   }
 
@@ -837,7 +885,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       return;
     }
-    if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null)
+    if (calculator
+            .getRegisteredWorkersOfClass(ConsensusThread.class) == null)
     {
       calculator.registerWorker(new ConsensusThread(this, ap));
     }
@@ -868,8 +917,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
       }
       if (doConsensus)
       {
-        if (calculator
-                .getRegisteredWorkersOfClass(ComplementConsensusThread.class) == null)
+        if (calculator.getRegisteredWorkersOfClass(
+                ComplementConsensusThread.class) == null)
         {
           calculator
                   .registerWorker(new ComplementConsensusThread(this, ap));
@@ -878,6 +927,20 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
   }
 
+  /**
+   * trigger update of information annotation
+   */
+  @Override
+  public void updateInformation(final AlignmentViewPanel ap)
+  {
+    if (calculator
+            .getRegisteredWorkersOfClass(InformationThread.class) == null)
+    {
+      calculator.registerWorker(new InformationThread(this, ap));
+    }
+
+  }
+
   // --------START Structure Conservation
   public void updateStrucConsensus(final AlignmentViewPanel ap)
   {
@@ -893,7 +956,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       return;
     }
-    if (calculator.getRegisteredWorkersOfClass(StrucConsensusThread.class) == null)
+    if (calculator.getRegisteredWorkersOfClass(
+            StrucConsensusThread.class) == null)
     {
       calculator.registerWorker(new StrucConsensusThread(this, ap));
     }
@@ -940,14 +1004,16 @@ public abstract class AlignmentViewport implements AlignViewportI,
     strucConsensus = null;
     conservation = null;
     quality = null;
-    groupConsensus = null;
-    groupConservation = null;
     hconsensus = null;
+    hconservation = null;
     hcomplementConsensus = null;
-    // colour scheme may hold reference to consensus
-    residueShading = null;
-    // TODO remove listeners from changeSupport?
+    occupancy = null;
+    calculator = null;
+    residueShading = null; // may hold a reference to Consensus
     changeSupport = null;
+    ranges = null;
+    currentTree = null;
+    selectionGroup = null;
     setAlignment(null);
   }
 
@@ -991,6 +1057,21 @@ public abstract class AlignmentViewport implements AlignViewportI,
   protected boolean showConsensusHistogram = true;
 
   /**
+   * should hmm profile be rendered by default
+   */
+  protected boolean showHMMSequenceLogo = false;
+
+  /**
+   * should hmm profile be rendered normalised to row height
+   */
+  protected boolean normaliseHMMSequenceLogo = false;
+
+  /**
+   * should information histograms be rendered by default
+   */
+  protected boolean showInformationHistogram = true;
+
+  /**
    * @return the showConsensusProfile
    */
   @Override
@@ -1000,6 +1081,15 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   /**
+   * @return the showInformationProfile
+   */
+  @Override
+  public boolean isShowHMMSequenceLogo()
+  {
+    return showHMMSequenceLogo;
+  }
+
+  /**
    * @param showSequenceLogo
    *          the new value
    */
@@ -1017,6 +1107,16 @@ public abstract class AlignmentViewport implements AlignViewportI,
     this.showSequenceLogo = showSequenceLogo;
   }
 
+  public void setShowHMMSequenceLogo(boolean showHMMSequenceLogo)
+  {
+    if (showHMMSequenceLogo != this.showHMMSequenceLogo)
+    {
+      this.showHMMSequenceLogo = showHMMSequenceLogo;
+      calculator.updateAnnotationFor(InformationThread.class);
+    }
+    this.showHMMSequenceLogo = showHMMSequenceLogo;
+  }
+
   /**
    * @param showConsensusHistogram
    *          the showConsensusHistogram to set
@@ -1027,6 +1127,15 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   /**
+   * @param showInformationHistogram
+   *          the showInformationHistogram to set
+   */
+  public void setShowInformationHistogram(boolean showInformationHistogram)
+  {
+    this.showInformationHistogram = showInformationHistogram;
+  }
+
+  /**
    * @return the showGroupConservation
    */
   public boolean isShowGroupConservation()
@@ -1072,6 +1181,17 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   /**
+   * 
+   * @return flag to indicate if the information content histogram should be
+   *         rendered by default
+   */
+  @Override
+  public boolean isShowInformationHistogram()
+  {
+    return this.showInformationHistogram;
+  }
+
+  /**
    * when set, updateAlignment will always ensure sequences are of equal length
    */
   private boolean padGaps = false;
@@ -1182,8 +1302,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
   {
     if (sequenceSetID != null)
     {
-      System.err
-              .println("Warning - overwriting a sequenceSetId for a viewport!");
+      System.err.println(
+              "Warning - overwriting a sequenceSetId for a viewport!");
     }
     sequenceSetID = new String(newid);
   }
@@ -1230,6 +1350,26 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   }
 
+  public void setIgnoreBelowBackground(boolean b, AlignmentViewPanel ap)
+  {
+    ignoreBelowBackGroundFrequencyCalculation = b;
+    if (ap != null)
+    {
+      updateInformation(ap);
+    }
+
+  }
+
+  public void setInfoLetterHeight(boolean b, AlignmentViewPanel ap)
+  {
+    infoLetterHeight = b;
+    if (ap != null)
+    {
+      updateInformation(ap);
+    }
+
+  }
+
   private long sgrouphash = -1, colselhash = -1;
 
   /**
@@ -1284,6 +1424,18 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return ignoreGapsInConsensusCalculation;
   }
 
+  @Override
+  public boolean isIgnoreBelowBackground()
+  {
+    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(
@@ -1329,7 +1481,10 @@ public abstract class AlignmentViewport implements AlignViewportI,
   public void removePropertyChangeListener(
           java.beans.PropertyChangeListener listener)
   {
-    changeSupport.removePropertyChangeListener(listener);
+    if (changeSupport != null)
+    {
+      changeSupport.removePropertyChangeListener(listener);
+    }
   }
 
   /**
@@ -1390,6 +1545,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
   // common hide/show seq stuff
   public void showAllHiddenSeqs()
   {
+    int startSeq = ranges.getStartSeq();
+    int endSeq = ranges.getEndSeq();
+
     if (alignment.getHiddenSequences().getSize() > 0)
     {
       if (selectionGroup == null)
@@ -1397,8 +1555,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
         selectionGroup = new SequenceGroup();
         selectionGroup.setEndRes(alignment.getWidth() - 1);
       }
-      List<SequenceI> tmp = alignment.getHiddenSequences().showAll(
-              hiddenRepSequences);
+      List<SequenceI> tmp = alignment.getHiddenSequences()
+              .showAll(hiddenRepSequences);
       for (SequenceI seq : tmp)
       {
         selectionGroup.addSequence(seq, false);
@@ -1407,6 +1565,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
       hiddenRepSequences = null;
 
+      ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
       firePropertyChange("alignment", null, alignment.getSequences());
       // used to set hasHiddenRows/hiddenRepSequences here, after the property
       // changed event
@@ -1416,8 +1576,11 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   public void showSequence(int index)
   {
-    List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(
-            index, hiddenRepSequences);
+    int startSeq = ranges.getStartSeq();
+    int endSeq = ranges.getEndSeq();
+
+    List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(index,
+            hiddenRepSequences);
     if (tmp.size() > 0)
     {
       if (selectionGroup == null)
@@ -1431,6 +1594,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
         selectionGroup.addSequence(seq, false);
         setSequenceAnnotationsVisible(seq, true);
       }
+
+      ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
       firePropertyChange("alignment", null, alignment.getSequences());
       sendSelection();
     }
@@ -1452,6 +1618,11 @@ public abstract class AlignmentViewport implements AlignViewportI,
 
   public void hideSequence(SequenceI[] seq)
   {
+    /*
+     * cache offset to first visible sequence
+     */
+    int startSeq = ranges.getStartSeq();
+
     if (seq != null)
     {
       for (int i = 0; i < seq.length; i++)
@@ -1459,6 +1630,7 @@ public abstract class AlignmentViewport implements AlignViewportI,
         alignment.getHiddenSequences().hideSequence(seq[i]);
         setSequenceAnnotationsVisible(seq[i], false);
       }
+      ranges.setStartSeq(startSeq);
       firePropertyChange("alignment", null, alignment.getSequences());
     }
   }
@@ -1488,8 +1660,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
 
     int gsize = selectionGroup.getSize();
-    SequenceI[] hseqs = selectionGroup.getSequences().toArray(
-            new SequenceI[gsize]);
+    SequenceI[] hseqs = selectionGroup.getSequences()
+            .toArray(new SequenceI[gsize]);
 
     hideSequence(hseqs);
     setSelectionGroup(null);
@@ -1579,8 +1751,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
    */
   public boolean isHiddenRepSequence(SequenceI seq)
   {
-    return (hiddenRepSequences != null && hiddenRepSequences
-            .containsKey(seq));
+    return (hiddenRepSequences != null
+            && hiddenRepSequences.containsKey(seq));
   }
 
   /**
@@ -1598,8 +1770,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
   @Override
   public int adjustForHiddenSeqs(int alignmentIndex)
   {
-    return alignment.getHiddenSequences().adjustForHiddenSeqs(
-            alignmentIndex);
+    return alignment.getHiddenSequences()
+            .adjustForHiddenSeqs(alignmentIndex);
   }
 
   @Override
@@ -1651,13 +1823,6 @@ public abstract class AlignmentViewport implements AlignViewportI,
   }
 
   @Override
-  public CigarArray getViewAsCigars(boolean selectedRegionOnly)
-  {
-    return new CigarArray(alignment, alignment.getHiddenColumns(),
-            (selectedRegionOnly ? selectionGroup : null));
-  }
-
-  @Override
   public jalview.datamodel.AlignmentView getAlignmentView(
           boolean selectedOnly)
   {
@@ -1669,10 +1834,10 @@ public abstract class AlignmentViewport implements AlignViewportI,
           boolean selectedOnly, boolean markGroups)
   {
     return new AlignmentView(alignment, alignment.getHiddenColumns(),
-            selectionGroup, alignment.getHiddenColumns() != null
+            selectionGroup,
+            alignment.getHiddenColumns() != null
                     && alignment.getHiddenColumns().hasHiddenColumns(),
-            selectedOnly,
-            markGroups);
+            selectedOnly, markGroups);
   }
 
   @Override
@@ -1718,8 +1883,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     if (alignment.getHiddenColumns() != null
             && alignment.getHiddenColumns().hasHiddenColumns())
     {
-      selection = alignment.getHiddenColumns().getVisibleSequenceStrings(
-              start, end, seqs);
+      selection = alignment.getHiddenColumns()
+              .getVisibleSequenceStrings(start, end, seqs);
     }
     else
     {
@@ -1788,8 +1953,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
         if (selectedOnly && selectionGroup != null)
         {
           alignment.getHiddenColumns().makeVisibleAnnotation(
-                  selectionGroup.getStartRes(),
-                  selectionGroup.getEndRes(), clone);
+                  selectionGroup.getStartRes(), selectionGroup.getEndRes(),
+                  clone);
         }
         else
         {
@@ -1838,6 +2003,16 @@ public abstract class AlignmentViewport implements AlignViewportI,
     {
       updateStrucConsensus(ap);
     }
+    initInformation();
+    updateInformation(ap);
+
+    List<SequenceI> hmmSequences;
+    hmmSequences = alignment.getHMMConsensusSequences();
+
+    for (SequenceI seq : hmmSequences)
+    {
+      seq.updateHMMMapping();
+    }
 
     // Reset endRes of groups if beyond alignment width
     int alWidth = alignment.getWidth();
@@ -1913,7 +2088,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
               MessageManager.getString("label.consensus_descr"),
               new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
       initConsensus(consensus);
-      initGapCounts();
+
+      initOccupancy();
 
       initComplementConsensus();
     }
@@ -1970,22 +2146,46 @@ public abstract class AlignmentViewport implements AlignViewportI,
     }
   }
 
+  @Override
+  public void initInformation()
+  {
+    for (SequenceI seq : alignment.getHMMConsensusSequences())
+    {
+      if (!seq.hasHMMAnnotation())
+      {
+        AlignmentAnnotation info = new AlignmentAnnotation(seq.getName(),
+                MessageManager.getString("label.information_description"),
+                new Annotation[1], 0f, 6.52f,
+                AlignmentAnnotation.BAR_GRAPH);
+        info.hasText = true;
+        info.autoCalculated = false;
+        info.sequenceRef = seq;
+        info.setCalcId(InformationThread.HMM_CALC_ID);
+        this.information.add(info);
+        hinformation.add(new Profiles(new ProfileI[1]));
+        alignment.addAnnotation(info);
+        seq.updateHMMMapping();
+        seq.addAlignmentAnnotation(info);
+      }
+    }
+  }
+
   // these should be extracted from the view model - style and settings for
   // derived annotation
-  private void initGapCounts()
+  private void initOccupancy()
   {
     if (showOccupancy)
     {
-      gapcounts = new AlignmentAnnotation("Occupancy",
+      occupancy = new AlignmentAnnotation("Occupancy",
               MessageManager.getString("label.occupancy_descr"),
-              new Annotation[1], 0f,
-              alignment.getHeight(), AlignmentAnnotation.BAR_GRAPH);
-      gapcounts.hasText = true;
-      gapcounts.autoCalculated = true;
-      gapcounts.scaleColLabel = true;
-      gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
+              new Annotation[1], 0f, alignment.getHeight(),
+              AlignmentAnnotation.BAR_GRAPH);
+      occupancy.hasText = true;
+      occupancy.autoCalculated = true;
+      occupancy.scaleColLabel = true;
+      occupancy.graph = AlignmentAnnotation.BAR_GRAPH;
 
-      alignment.addAnnotation(gapcounts);
+      alignment.addAnnotation(occupancy);
     }
   }
 
@@ -1997,8 +2197,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
       {
         conservation = new AlignmentAnnotation("Conservation",
                 MessageManager.formatMessage("label.conservation_descr",
-                        getConsPercGaps()), new Annotation[1],
-                0f, 11f, AlignmentAnnotation.BAR_GRAPH);
+                        getConsPercGaps()),
+                new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
         conservation.hasText = true;
         conservation.autoCalculated = true;
         alignment.addAnnotation(conservation);
@@ -2119,6 +2319,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
@@ -2156,6 +2359,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)
         {
@@ -2478,8 +2684,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     viewStyle = new ViewStyle(settingsForView);
     if (residueShading != null)
     {
-      residueShading.setConservationApplied(settingsForView
-              .isConservationColourSelected());
+      residueShading.setConservationApplied(
+              settingsForView.isConservationColourSelected());
     }
   }
 
@@ -2647,7 +2853,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
     return sortAnnotationsBy;
   }
 
-  public void setSortAnnotationsBy(SequenceAnnotationOrder sortAnnotationsBy)
+  public void setSortAnnotationsBy(
+          SequenceAnnotationOrder sortAnnotationsBy)
   {
     this.sortAnnotationsBy = sortAnnotationsBy;
   }
@@ -2725,8 +2932,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
       return 0;
     }
     boolean iAmProtein = !getAlignment().isNucleotide();
-    AlignmentI proteinAlignment = iAmProtein ? getAlignment() : complement
-            .getAlignment();
+    AlignmentI proteinAlignment = iAmProtein ? getAlignment()
+            : complement.getAlignment();
     if (proteinAlignment == null)
     {
       return 0;
@@ -2757,7 +2964,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
      */
     int lastSeq = alignment.getHeight() - 1;
     List<AlignedCodonFrame> seqMappings = null;
-    for (int seqNo = ranges.getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
+    for (int seqNo = ranges
+            .getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
     {
       sequence = getAlignment().getSequenceAt(seqNo);
       if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
@@ -2768,9 +2976,9 @@ public abstract class AlignmentViewport implements AlignViewportI,
       {
         continue;
       }
-      seqMappings = MappingUtils
-              .findMappingsForSequenceAndOthers(sequence, mappings,
-                      getCodingComplement().getAlignment().getSequences());
+      seqMappings = MappingUtils.findMappingsForSequenceAndOthers(sequence,
+              mappings,
+              getCodingComplement().getAlignment().getSequences());
       if (!seqMappings.isEmpty())
       {
         break;
@@ -2853,6 +3061,8 @@ public abstract class AlignmentViewport implements AlignViewportI,
    */
   private SearchResultsI searchResults = null;
 
+  protected TreeModel currentTree = null;
+
   @Override
   public boolean hasSearchResults()
   {
@@ -2870,4 +3080,70 @@ public abstract class AlignmentViewport implements AlignViewportI,
   {
     return searchResults;
   }
+
+  /**
+   * get the consensus sequence as displayed under the PID consensus annotation
+   * row.
+   * 
+   * @return consensus sequence as a new sequence object
+   */
+  public SequenceI getConsensusSeq()
+  {
+    if (consensus == null)
+    {
+      updateConsensus(null);
+    }
+    if (consensus == null)
+    {
+      return null;
+    }
+    StringBuffer seqs = new StringBuffer();
+    for (int i = 0; i < consensus.annotations.length; i++)
+    {
+      Annotation annotation = consensus.annotations[i];
+      if (annotation != null)
+      {
+        String description = annotation.description;
+        if (description != null && description.startsWith("["))
+        {
+          // consensus is a tie - just pick the first one
+          seqs.append(description.charAt(1));
+        }
+        else
+        {
+          seqs.append(annotation.displayCharacter);
+        }
+      }
+    }
+
+    SequenceI sq = new Sequence("Consensus", seqs.toString());
+    sq.setDescription("Percentage Identity Consensus "
+            + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
+    return sq;
+  }
+
+  public boolean hasReferenceAnnotation()
+  {
+    AlignmentAnnotation[] annots = this.alignment.getAlignmentAnnotation();
+    for (AlignmentAnnotation annot : annots)
+    {
+      if ("RF".equals(annot.label) || annot.label.contains("Reference"))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public void setCurrentTree(TreeModel tree)
+  {
+    currentTree = tree;
+  }
+
+  @Override
+  public TreeModel getCurrentTree()
+  {
+    return currentTree;
+  }
 }