JAL - 3690 AlignCalc rebuilt - FutureTask-based manager
[jalview.git] / src / jalview / workers / InformationThread.java
index 28b4962..c8084b9 100644 (file)
@@ -12,6 +12,7 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.util.MessageManager;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -24,8 +25,6 @@ public class InformationThread extends AlignCalcWorker
 {
   public static final String HMM_CALC_ID = "HMM";
 
-  private float max = 0f;
-
   /**
    * Constructor
    * 
@@ -45,66 +44,38 @@ public class InformationThread extends AlignCalcWorker
   @Override
   public void run()
   {
-    if (calcMan.isPending(this))
+    if (alignViewport.getAlignment().getHmmSequences().isEmpty())
     {
       return;
     }
-    calcMan.notifyStart(this);
-    // long started = System.currentTimeMillis();
-
-    try
+    if (alignViewport.isClosed())
     {
-      if (calcMan.isPending(this))
-      {
-        // another instance of this is waiting to run
-        calcMan.workerComplete(this);
-        return;
-      }
-      while (!calcMan.notifyWorking(this))
-      {
-        // another thread in progress, wait my turn
-        try
-        {
-          if (ap != null)
-          {
-            ap.paintAlignment(false, false);
-          }
-          Thread.sleep(200);
-        } catch (Exception ex)
-        {
-          ex.printStackTrace();
-        }
-      }
-      if (alignViewport.isClosed())
-      {
-        abortAndDestroy();
-        return;
-      }
-      AlignmentI alignment = alignViewport.getAlignment();
+      abortAndDestroy();
+      return;
+    }
 
-      int aWidth = alignment == null ? -1 : alignment.getWidth();
+    AlignmentI alignment = alignViewport.getAlignment();
+    int aWidth = alignment == null ? -1 : alignment.getWidth();
+    if (aWidth < 0)
+    {
+      return;
+    }
 
-      if (aWidth < 0)
-      {
-        calcMan.workerComplete(this);
-        return;
-      }
+    /*
+     * compute information profiles for any HMM consensus sequences
+     * for the alignment or sub-groups
+     */
+    computeProfiles(alignment);
 
-      computeProfiles(alignment);
-      updateAnnotation();
+    /*
+     * construct the corresponding annotations
+     */
+    updateAnnotation();
 
-      if (ap != null)
-      {
-        ap.adjustAnnotationHeight();
-        ap.paintAlignment(true, true);
-      }
-    } catch (OutOfMemoryError error)
-    {
-      calcMan.disableWorker(this);
-      ap.raiseOOMWarning("calculating information", error);
-    } finally
+    if (ap != null)
     {
-      calcMan.workerComplete(this);
+      ap.adjustAnnotationHeight();
+      ap.paintAlignment(true, true);
     }
   }
 
@@ -123,12 +94,12 @@ public class InformationThread extends AlignCalcWorker
     /*
      * alignment HMM profile
      */
-    SequenceI seq = alignment.getHmmConsensus();
-    if (seq != null)
+    List<SequenceI> seqs = alignment.getHmmSequences();
+    if (!seqs.isEmpty())
     {
-      HiddenMarkovModel hmm = seq.getHMM();
+      HiddenMarkovModel hmm = seqs.get(0).getHMM();
       ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
-              0, width, true, alignViewport.isIgnoreBelowBackground(),
+              0, width, alignViewport.isIgnoreBelowBackground(),
               alignViewport.isInfoLetterHeight());
       alignViewport.setHmmProfiles(hmmProfiles);
     }
@@ -139,12 +110,12 @@ public class InformationThread extends AlignCalcWorker
     List<SequenceGroup> groups = alignment.getGroups();
     for (SequenceGroup group : groups)
     {
-      seq = group.getHmmConsensus();
-      if (seq != null)
+      seqs = group.getHmmSequences();
+      if (!seqs.isEmpty())
       {
-        HiddenMarkovModel hmm = seq.getHMM();
+        HiddenMarkovModel hmm = seqs.get(0).getHMM();
         ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
-                0, width, true, group.isIgnoreBelowBackground(),
+                0, width, group.isIgnoreBelowBackground(),
                 group.isUseInfoLetterHeight());
         group.setHmmProfiles(hmmProfiles);
       }
@@ -168,7 +139,7 @@ public class InformationThread extends AlignCalcWorker
    */
   protected AlignmentAnnotation getGapAnnotation()
   {
-    return alignViewport.getOccupancyAnnotation();
+               return alignViewport.getAlignmentGapAnnotation();
   }
 
   /**
@@ -181,58 +152,78 @@ public class InformationThread extends AlignCalcWorker
   {
     AlignmentI alignment = alignViewport.getAlignment();
 
-    this.max = 0f;
+    float maxInformation = 0f;
+    List<AlignmentAnnotation> infos = new ArrayList<>();
 
     /*
      * annotation for alignment HMM consensus if present
      */
-    SequenceI hmmSeq = alignment.getHmmConsensus();
-    ProfilesI profile = alignViewport.getHmmProfiles();
-    updateInformationAnnotation(hmmSeq, profile, null);
+    List<SequenceI> hmmSeqs = alignment.getHmmSequences();
+    if (!hmmSeqs.isEmpty())
+    {
+      ProfilesI profile = alignViewport.getHmmProfiles();
+      float m = updateInformationAnnotation(hmmSeqs.get(0), profile, null,
+              infos);
+      maxInformation = Math.max(maxInformation, m);
+    }
 
     /*
      * annotation for group HMM consensus if present
      */
     for (SequenceGroup group : alignment.getGroups())
     {
-      hmmSeq = group.getHmmConsensus();
-      ProfilesI profiles = group.getHmmProfiles();
-      updateInformationAnnotation(hmmSeq, profiles, group);
+      hmmSeqs = group.getHmmSequences();
+      if (!hmmSeqs.isEmpty())
+      {
+        ProfilesI profiles = group.getHmmProfiles();
+        float m = updateInformationAnnotation(hmmSeqs.get(0), profiles,
+                group, infos);
+        maxInformation = Math.max(maxInformation, m);
+      }
     }
 
     /*
-     * todo: this.max is not used, but acquires the maximum value of
-     * information in any of the annotations; set this as graphMax in all
-     * annotations to have them all scaled the same
+     * maxInformation holds the maximum value of information score;
+     * set this as graphMax in all annotations to scale them all the same
      */
+    for (AlignmentAnnotation ann : infos)
+    {
+      ann.graphMax = maxInformation;
+    }
   }
 
   /**
    * Updates (and first constructs if necessary) an HMM Profile information
    * content annotation for a sequence. The <code>group</code> argument is null
-   * for the whole alignment annotation, not null for a subgroup annotation.
+   * for the whole alignment annotation, not null for a subgroup annotation. The
+   * updated annotation is added to the <code>infos</code> list. Answers the
+   * maximum information content value of any annotation (for use as a scaling
+   * factor for display).
    * 
    * @param seq
    * @param profile
    * @param group
+   * @param infos
    * @return
    */
-  protected AlignmentAnnotation updateInformationAnnotation(SequenceI seq,
-          ProfilesI profile, SequenceGroup group)
+  protected float updateInformationAnnotation(SequenceI seq,
+          ProfilesI profile, SequenceGroup group,
+          List<AlignmentAnnotation> infos)
   {
     if (seq == null || profile == null)
     {
-      return null;
+      return 0f;
     }
 
     AlignmentAnnotation ann = findOrCreateAnnotation(seq, group);
 
     seq.addAlignmentAnnotation(ann);
+    infos.add(ann);
 
-    max = AAFrequency.completeInformation(ann, profile,
+    float max = AAFrequency.completeInformation(ann, profile,
             profile.getStartColumn(), profile.getEndColumn() + 1);
 
-    return ann;
+    return max;
   }
 
   /**
@@ -266,6 +257,7 @@ public class InformationThread extends AlignCalcWorker
         {
           info = ann;
           info.setSequenceRef(seq);
+          info.label = seq.getName(); // in case group name changed!
           break;
         }
       }