JAL - 3690 AlignCalc rebuilt - FutureTask-based manager
[jalview.git] / src / jalview / viewmodel / AlignmentViewport.java
index f2ab8a6..77210ee 100644 (file)
@@ -24,6 +24,8 @@ import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.analysis.Conservation;
 import jalview.analysis.TreeModel;
 import jalview.api.AlignCalcManagerI;
+import jalview.api.AlignCalcManagerI2;
+import jalview.api.AlignCalcWorkerI;
 import jalview.api.AlignExportSettingsI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
@@ -57,8 +59,10 @@ import jalview.util.MappingUtils;
 import jalview.util.MessageManager;
 import jalview.viewmodel.styles.ViewStyle;
 import jalview.workers.AlignCalcManager;
+import jalview.workers.AlignCalcManager2;
 import jalview.workers.ComplementConsensusThread;
 import jalview.workers.ConsensusThread;
+import jalview.workers.InformationThread;
 import jalview.workers.StrucConsensusThread;
 
 import java.awt.Color;
@@ -103,6 +107,27 @@ public abstract class AlignmentViewport
    * alignment displayed in the viewport. Please use get/setter
    */
   protected AlignmentI alignment;
+  
+  /*
+   * probably unused indicator that view is of a dataset rather than an
+   * alignment
+   */
+
+  protected boolean ignoreBelowBackGroundFrequencyCalculation = false;
+
+  protected boolean infoLetterHeight = false;
+
+  protected AlignmentAnnotation occupancy;
+  
+  /**
+   * results of alignment consensus analysis for visible portion of view
+   */
+  protected ProfilesI consensusProfiles;
+
+  /**
+   * HMM profile for the alignment
+   */
+  protected ProfilesI hmmProfiles;
 
   public AlignmentViewport(AlignmentI al)
   {
@@ -590,7 +615,7 @@ public abstract class AlignmentViewport
    * alignment
    */
   protected boolean isDataset = false;
-
+  
   public void setDataset(boolean b)
   {
     isDataset = b;
@@ -612,7 +637,7 @@ public abstract class AlignmentViewport
   protected boolean ignoreGapsInConsensusCalculation = false;
 
   protected ResidueShaderI residueShading = new ResidueShader();
-
+  
   @Override
   public void setGlobalColourScheme(ColourSchemeI cs)
   {
@@ -686,7 +711,7 @@ public abstract class AlignmentViewport
   {
     return residueShading;
   }
-
+  
   protected AlignmentAnnotation consensus;
 
   protected AlignmentAnnotation complementConsensus;
@@ -720,7 +745,7 @@ public abstract class AlignmentViewport
   protected Hashtable<String, Object>[] hStrucConsensus = null;
 
   protected Conservation hconservation = null;
-
+  
   @Override
   public void setConservation(Conservation cons)
   {
@@ -759,6 +784,18 @@ public abstract class AlignmentViewport
   }
 
   @Override
+  public void setHmmProfiles(ProfilesI info)
+  {
+    hmmProfiles = info;
+  }
+
+  @Override
+  public ProfilesI getHmmProfiles()
+  {
+    return hmmProfiles;
+  }
+
+  @Override
   public Hashtable<String, Object>[] getComplementConsensusHash()
   {
     return hcomplementConsensus;
@@ -814,7 +851,7 @@ public abstract class AlignmentViewport
     return strucConsensus;
   }
 
-  protected AlignCalcManagerI calculator = new AlignCalcManager();
+  protected AlignCalcManagerI2 calculator = new AlignCalcManager2();
 
   /**
    * trigger update of conservation annotation
@@ -828,8 +865,8 @@ public abstract class AlignmentViewport
     {
       return;
     }
-    if (calculator.getRegisteredWorkersOfClass(
-            jalview.workers.ConservationThread.class) == null)
+    if (calculator.getWorkersOfClass(
+            jalview.workers.ConservationThread.class).isEmpty())
     {
       calculator.registerWorker(
               new jalview.workers.ConservationThread(this, ap));
@@ -846,8 +883,7 @@ public abstract class AlignmentViewport
     {
       return;
     }
-    if (calculator
-            .getRegisteredWorkersOfClass(ConsensusThread.class) == null)
+    if (calculator.getWorkersOfClass(ConsensusThread.class).isEmpty())
     {
       calculator.registerWorker(new ConsensusThread(this, ap));
     }
@@ -878,16 +914,23 @@ public abstract class AlignmentViewport
       }
       if (doConsensus)
       {
-        if (calculator.getRegisteredWorkersOfClass(
-                ComplementConsensusThread.class) == null)
+        if (calculator.getWorkersOfClass(ComplementConsensusThread.class).isEmpty())
         {
-          calculator
-                  .registerWorker(new ComplementConsensusThread(this, ap));
+          calculator.registerWorker(new ComplementConsensusThread(this, ap));
         }
       }
     }
   }
 
+  @Override
+  public void initInformationWorker(final AlignmentViewPanel ap)
+  {
+    if (calculator.getWorkersOfClass(InformationThread.class).isEmpty())
+    {
+      calculator.registerWorker(new InformationThread(this, ap));
+    }
+  }
+
   // --------START Structure Conservation
   public void updateStrucConsensus(final AlignmentViewPanel ap)
   {
@@ -903,8 +946,7 @@ public abstract class AlignmentViewport
     {
       return;
     }
-    if (calculator.getRegisteredWorkersOfClass(
-            StrucConsensusThread.class) == null)
+    if (calculator.getWorkersOfClass(StrucConsensusThread.class).isEmpty())
     {
       calculator.registerWorker(new StrucConsensusThread(this, ap));
     }
@@ -923,7 +965,7 @@ public abstract class AlignmentViewport
     {
       return false;
     }
-    if (calculator.workingInvolvedWith(alignmentAnnotation))
+    if (calculator.isWorkingWithAnnotation(alignmentAnnotation))
     {
       // System.err.println("grey out ("+alignmentAnnotation.label+")");
       return true;
@@ -951,6 +993,7 @@ public abstract class AlignmentViewport
     strucConsensus = null;
     conservation = null;
     quality = null;
+    consensusProfiles = null;
     groupConsensus = null;
     groupConservation = null;
     hconsensus = null;
@@ -975,7 +1018,7 @@ public abstract class AlignmentViewport
   }
 
   @Override
-  public AlignCalcManagerI getCalcManager()
+  public AlignCalcManagerI2 getCalcManager()
   {
     return calculator;
   }
@@ -1006,6 +1049,21 @@ public abstract class AlignmentViewport
   protected boolean showConsensusHistogram = true;
 
   /**
+   * should hmm profile be rendered by default
+   */
+  protected boolean hmmShowSequenceLogo = false;
+
+  /**
+   * should hmm profile be rendered normalised to row height
+   */
+  protected boolean hmmNormaliseSequenceLogo = false;
+
+  /**
+   * should information histograms be rendered by default
+   */
+  protected boolean hmmShowHistogram = true;
+
+  /**
    * @return the showConsensusProfile
    */
   @Override
@@ -1015,6 +1073,15 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * @return the showInformationProfile
+   */
+  @Override
+  public boolean isShowHMMSequenceLogo()
+  {
+    return hmmShowSequenceLogo;
+  }
+
+  /**
    * @param showSequenceLogo
    *          the new value
    */
@@ -1025,13 +1092,31 @@ public abstract class AlignmentViewport
       // TODO: decouple settings setting from calculation when refactoring
       // annotation update method from alignframe to viewport
       this.showSequenceLogo = showSequenceLogo;
-      calculator.updateAnnotationFor(ConsensusThread.class);
-      calculator.updateAnnotationFor(ComplementConsensusThread.class);
-      calculator.updateAnnotationFor(StrucConsensusThread.class);
+      for (AlignCalcWorkerI worker : calculator.getWorkers())
+      {
+        if (worker.getClass().equals(ConsensusThread.class) ||
+                worker.getClass().equals(ComplementConsensusThread.class) ||
+                worker.getClass().equals(StrucConsensusThread.class))
+        {
+          worker.updateAnnotation();
+        }
+      }
     }
     this.showSequenceLogo = showSequenceLogo;
   }
 
+  public void setShowHMMSequenceLogo(boolean showHMMSequenceLogo)
+  {
+    if (showHMMSequenceLogo != this.hmmShowSequenceLogo)
+    {
+      this.hmmShowSequenceLogo = showHMMSequenceLogo;
+      // TODO: updateAnnotation if description (tooltip) will show
+      // profile in place of information content?
+      // calculator.updateAnnotationFor(InformationThread.class);
+    }
+    this.hmmShowSequenceLogo = showHMMSequenceLogo;
+  }
+
   /**
    * @param showConsensusHistogram
    *          the showConsensusHistogram to set
@@ -1042,6 +1127,14 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * @param showInformationHistogram
+   */
+  public void setShowInformationHistogram(boolean showInformationHistogram)
+  {
+    this.hmmShowHistogram = showInformationHistogram;
+  }
+
+  /**
    * @return the showGroupConservation
    */
   public boolean isShowGroupConservation()
@@ -1087,6 +1180,17 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * 
+   * @return flag to indicate if the information content histogram should be
+   *         rendered by default
+   */
+  @Override
+  public boolean isShowInformationHistogram()
+  {
+    return this.hmmShowHistogram;
+  }
+
+  /**
    * when set, updateAlignment will always ensure sequences are of equal length
    */
   private boolean padGaps = false;
@@ -1242,7 +1346,16 @@ public abstract class AlignmentViewport
                 ignoreGapsInConsensusCalculation);
       }
     }
+  }
 
+  public void setIgnoreBelowBackground(boolean b, AlignmentViewPanel ap)
+  {
+    ignoreBelowBackGroundFrequencyCalculation = b;
+  }
+
+  public void setInfoLetterHeight(boolean b, AlignmentViewPanel ap)
+  {
+    infoLetterHeight = b;
   }
 
   private long sgrouphash = -1, colselhash = -1;
@@ -1299,6 +1412,18 @@ public abstract class AlignmentViewport
     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(
@@ -1323,21 +1448,6 @@ public abstract class AlignmentViewport
    */
   private boolean followHighlight = true;
 
-  private boolean disableFastPaint; // BH 2019.04.18
-
-  /**
-   * BH 2019.04.18 When gap filling is on and a modification is made to fill
-   * those, we need to disallow fast painting for paste just once
-   * 
-   * @return
-   */
-  public boolean isFastPaintDisabled()
-  {
-    boolean ret = disableFastPaint;
-    disableFastPaint = false;
-    return ret;
-  }
-
   /**
    * Property change listener for changes in alignment
    * 
@@ -1872,11 +1982,7 @@ public abstract class AlignmentViewport
   {
     if (isPadGaps())
     {
-      if (alignment.padGaps())
-      {
-        // the new alignment has been modified -- can't fast paint
-        disableFastPaint = true;
-      }
+      alignment.padGaps();
     }
     if (autoCalculateConsensus)
     {
@@ -1912,7 +2018,6 @@ public abstract class AlignmentViewport
 
     updateAllColourSchemes();
     calculator.restartWorkers();
-    // alignment.adjustSequenceAnnotations();
   }
 
   /**
@@ -1965,6 +2070,7 @@ public abstract class AlignmentViewport
               MessageManager.getString("label.consensus_descr"),
               new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
       initConsensus(consensus);
+
       initGapCounts();
 
       initComplementConsensus();
@@ -2171,6 +2277,9 @@ public abstract class AlignmentViewport
     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
@@ -2208,6 +2317,9 @@ public abstract class AlignmentViewport
           sg.setshowSequenceLogo(showprf);
           sg.setShowConsensusHistogram(showConsHist);
           sg.setNormaliseSequenceLogo(normLogo);
+          sg.setShowHMMSequenceLogo(showHMMPrf);
+          sg.setShowInformationHistogram(showInfoHist);
+          sg.setNormaliseHMMSequenceLogo(normHMMLogo);
         }
         if (conv)
         {
@@ -2286,7 +2398,7 @@ public abstract class AlignmentViewport
   public void clearSequenceColours()
   {
     sequenceColours.clear();
-  };
+  }
 
   @Override
   public AlignViewportI getCodingComplement()
@@ -2739,6 +2851,30 @@ public abstract class AlignmentViewport
     viewStyle.setProteinFontAsCdna(b);
   }
 
+  @Override
+  public void setShowComplementFeatures(boolean b)
+  {
+    viewStyle.setShowComplementFeatures(b);
+  }
+
+  @Override
+  public boolean isShowComplementFeatures()
+  {
+    return viewStyle.isShowComplementFeatures();
+  }
+
+  @Override
+  public void setShowComplementFeaturesOnTop(boolean b)
+  {
+    viewStyle.setShowComplementFeaturesOnTop(b);
+  }
+
+  @Override
+  public boolean isShowComplementFeaturesOnTop()
+  {
+    return viewStyle.isShowComplementFeaturesOnTop();
+  }
+
   /**
    * @return true if view should scroll to show the highlighted region of a
    *         sequence
@@ -2968,6 +3104,19 @@ public abstract class AlignmentViewport
     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)
   {
@@ -3010,6 +3159,27 @@ public abstract class AlignmentViewport
     return ed;
   }
   
+  @Override
+  public boolean isNormaliseSequenceLogo()
+  {
+    return normaliseSequenceLogo;
+  }
+
+  public void setNormaliseSequenceLogo(boolean state)
+  {
+    normaliseSequenceLogo = state;
+  }
+
+  @Override
+  public boolean isNormaliseHMMSequenceLogo()
+  {
+    return hmmNormaliseSequenceLogo;
+  }
+
+  public void setNormaliseHMMSequenceLogo(boolean state)
+  {
+    hmmNormaliseSequenceLogo = state;
+  }
   /**
    * flag set to indicate if structure views might be out of sync with sequences
    * in the alignment
@@ -3073,4 +3243,46 @@ public abstract class AlignmentViewport
       codingComplement.setUpdateStructures(needToUpdateStructureViews);
     }
   }
+
+  /**
+   * Filters out sequences with an eValue higher than the specified value. The
+   * filtered sequences are hidden or deleted. Sequences with no eValues are also
+   * filtered out.
+   * 
+   * @param eValue
+   * @param delete
+   */
+  public void filterByEvalue(double eValue)
+  {
+    for (SequenceI seq : alignment.getSequencesArray())
+    {
+      if ((seq.getAnnotation("Search Scores") == null
+              || seq.getAnnotation("Search Scores")[0].getEValue() > eValue)
+              && seq.getHMM() == null)
+      {
+        hideSequence(new SequenceI[] { seq });
+      }
+    }
+  }
+
+  /**
+   * Filters out sequences with an score lower than the specified value. The
+   * filtered sequences are hidden or deleted.
+   * 
+   * @param score
+   * @param delete
+   */
+  public void filterByScore(double score)
+  {
+    for (SequenceI seq : alignment.getSequencesArray())
+    {
+      if ((seq.getAnnotation("Search Scores") == null
+              || seq.getAnnotation("Search Scores")[0]
+                      .getBitScore() < score)
+              && seq.getHMM() == null)
+      {
+        hideSequence(new SequenceI[] { seq });
+      }
+    }
+  }
 }