Merge branch 'develop' into bug/JAL-4421_customise_volume_name_of_DMG_installers
[jalview.git] / src / jalview / viewmodel / AlignmentViewport.java
index 42768a6..d26f023 100644 (file)
@@ -33,6 +33,7 @@ import java.util.List;
 import java.util.Map;
 
 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.analysis.Connectivity;
 import jalview.analysis.Conservation;
 import jalview.analysis.TreeModel;
 import jalview.api.AlignCalcManagerI;
@@ -76,6 +77,7 @@ import jalview.viewmodel.styles.ViewStyle;
 import jalview.workers.AlignCalcManager;
 import jalview.workers.ComplementConsensusThread;
 import jalview.workers.ConsensusThread;
+import jalview.workers.SecondaryStructureConsensusThread;
 import jalview.workers.StrucConsensusThread;
 
 /**
@@ -697,6 +699,8 @@ public abstract class AlignmentViewport
   }
 
   protected AlignmentAnnotation consensus;
+  
+  protected AlignmentAnnotation secondaryStructureConsensus;
 
   protected AlignmentAnnotation complementConsensus;
 
@@ -709,6 +713,8 @@ public abstract class AlignmentViewport
   protected AlignmentAnnotation quality;
 
   protected AlignmentAnnotation[] groupConsensus;
+  
+  protected AlignmentAnnotation[] groupSSConsensus;
 
   protected AlignmentAnnotation[] groupConservation;
 
@@ -716,6 +722,10 @@ public abstract class AlignmentViewport
    * results of alignment consensus analysis for visible portion of view
    */
   protected ProfilesI hconsensus = null;
+  
+  protected ProfilesI hSSConsensus = null;
+  
+  
 
   /**
    * results of cDNA complement consensus visible portion of view
@@ -753,7 +763,13 @@ public abstract class AlignmentViewport
   {
     this.hconsensus = hconsensus;
   }
-
+  
+  @Override
+  public void setSequenceSSConsensusHash(ProfilesI hSSConsensus)
+  {
+    this.hSSConsensus = hSSConsensus;
+  }
+  
   @Override
   public void setComplementConsensusHash(
           Hashtable<String, Object>[] hconsensus)
@@ -766,6 +782,12 @@ public abstract class AlignmentViewport
   {
     return hconsensus;
   }
+  
+  @Override
+  public ProfilesI getSequenceSSConsensusHash()
+  {
+    return hSSConsensus;
+  }
 
   @Override
   public Hashtable<String, Object>[] getComplementConsensusHash()
@@ -805,6 +827,14 @@ public abstract class AlignmentViewport
     return consensus;
   }
 
+  
+  @Override
+  public AlignmentAnnotation getAlignmentSecondaryStructureConsensusAnnotation()
+  {
+    return secondaryStructureConsensus;
+  }
+  
+
   @Override
   public AlignmentAnnotation getAlignmentGapAnnotation()
   {
@@ -896,6 +926,26 @@ public abstract class AlignmentViewport
       }
     }
   }
+  
+  
+  
+
+  /**
+   * trigger update of consensus annotation
+   */
+  public void updateSecondaryStructureConsensus(final AlignmentViewPanel ap)
+  {
+    // see note in mantis : issue number 8585
+    if (secondaryStructureConsensus == null || !autoCalculateConsensus)
+    {
+      return;
+    }
+    if (calculator
+            .getRegisteredWorkersOfClass(SecondaryStructureConsensusThread.class) == null)
+    {
+      calculator.registerWorker(new SecondaryStructureConsensusThread(this, ap));
+    }
+  }
 
   // --------START Structure Conservation
   public void updateStrucConsensus(final AlignmentViewPanel ap)
@@ -934,7 +984,8 @@ public abstract class AlignmentViewport
     }
     if (calculator.workingInvolvedWith(alignmentAnnotation))
     {
-      // jalview.bin.Console.errPrintln("grey out ("+alignmentAnnotation.label+")");
+      // jalview.bin.Console.errPrintln("grey out
+      // ("+alignmentAnnotation.label+")");
       return true;
     }
     return false;
@@ -958,6 +1009,7 @@ public abstract class AlignmentViewport
     consensus = null;
     complementConsensus = null;
     strucConsensus = null;
+    secondaryStructureConsensus = null;
     conservation = null;
     quality = null;
     groupConsensus = null;
@@ -1004,6 +1056,8 @@ public abstract class AlignmentViewport
    * should consensus profile be rendered by default
    */
   protected boolean showSequenceLogo = false;
+  
+  protected boolean showSequenceSSLogo = false;
 
   /**
    * should consensus profile be rendered normalised to row height
@@ -1014,6 +1068,13 @@ public abstract class AlignmentViewport
    * should consensus histograms be rendered by default
    */
   protected boolean showConsensusHistogram = true;
+  
+  protected boolean showSSConsensusHistogram = true;
+
+  public void setShowSSConsensusHistogram(boolean showSSConsensusHistogram)
+  {
+    this.showSSConsensusHistogram = showSSConsensusHistogram;
+  }
 
   /**
    * @return the showConsensusProfile
@@ -1023,6 +1084,12 @@ public abstract class AlignmentViewport
   {
     return showSequenceLogo;
   }
+  
+  @Override
+  public boolean isShowSequenceSSLogo()
+  {
+    return showSequenceSSLogo;
+  }
 
   /**
    * @param showSequenceLogo
@@ -1041,6 +1108,18 @@ public abstract class AlignmentViewport
     }
     this.showSequenceLogo = showSequenceLogo;
   }
+  
+  public void setShowSequenceSSLogo(boolean showSequenceSSLogo)
+  {
+    if (showSequenceSSLogo != this.showSequenceSSLogo)
+    {
+      // TODO: decouple settings setting from calculation when refactoring
+      // annotation update method from alignframe to viewport
+      this.showSequenceSSLogo = showSequenceSSLogo;
+      calculator.updateAnnotationFor(SecondaryStructureConsensusThread.class);
+    }
+    this.showSequenceSSLogo = showSequenceSSLogo;
+  }
 
   /**
    * @param showConsensusHistogram
@@ -1095,6 +1174,12 @@ public abstract class AlignmentViewport
   {
     return this.showConsensusHistogram;
   }
+  
+  @Override
+  public boolean isShowSSConsensusHistogram()
+  {
+    return this.showSSConsensusHistogram;
+  }
 
   /**
    * when set, updateAlignment will always ensure sequences are of equal length
@@ -1246,6 +1331,7 @@ public abstract class AlignmentViewport
     if (ap != null)
     {
       updateConsensus(ap);
+      updateSecondaryStructureConsensus(ap);
       if (residueShading != null)
       {
         residueShading.setThreshold(residueShading.getThreshold(),
@@ -1318,7 +1404,9 @@ public abstract class AlignmentViewport
 
   protected boolean showQuality = true;
 
-  protected boolean showConsensus = true;
+  protected boolean showConsensus = true;  
+
+  protected boolean showSSConsensus = false;
 
   protected boolean showOccupancy = true;
 
@@ -1376,6 +1464,12 @@ public abstract class AlignmentViewport
     changeSupport.firePropertyChange(prop, oldvalue, newvalue);
   }
 
+  @Override
+  public void notifyAlignmentChanged()
+  {
+    firePropertyChange("alignment", null, alignment);
+  }
+
   // common hide/show column stuff
 
   public void hideSelectedColumns()
@@ -1871,6 +1965,7 @@ public abstract class AlignmentViewport
     if (autoCalculateConsensus)
     {
       updateConsensus(ap);
+      updateSecondaryStructureConsensus(ap);
     }
     if (hconsensus != null && autoCalculateConsensus)
     {
@@ -1954,13 +2049,19 @@ public abstract class AlignmentViewport
       consensus = new AlignmentAnnotation("Consensus",
               MessageManager.getString("label.consensus_descr"),
               new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+      
+      secondaryStructureConsensus = new AlignmentAnnotation(MessageManager.getString("label.ssconsensus_label"),
+              MessageManager.getString("label.ssconsensus_descr"),
+              new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+      
       initConsensus(consensus);
+      initSSConsensus(secondaryStructureConsensus);
       initGapCounts();
-
       initComplementConsensus();
     }
   }
 
+
   /**
    * If this is a protein alignment and there are mappings to cDNA, adds the
    * cDNA consensus annotation and returns true, else returns false.
@@ -2011,6 +2112,17 @@ public abstract class AlignmentViewport
       alignment.addAnnotation(aa);
     }
   }
+  
+  private void initSSConsensus(AlignmentAnnotation aa)
+  {
+    aa.hasText = true;
+    aa.autoCalculated = true;
+
+    if (showSSConsensus)
+    {
+      alignment.addAnnotation(aa);
+    }
+  }
 
   // these should be extracted from the view model - style and settings for
   // derived annotation
@@ -2132,7 +2244,7 @@ public abstract class AlignmentViewport
 
         if (aa.graph > 0)
         {
-          aa.height += aa.graphHeight+20;
+          aa.height += aa.graphHeight + 20;
         }
 
         if (aa.height == 0)
@@ -2159,7 +2271,9 @@ public abstract class AlignmentViewport
     boolean conv = isShowGroupConservation();
     boolean cons = isShowGroupConsensus();
     boolean showprf = isShowSequenceLogo();
+    boolean showSSprf = isShowSequenceSSLogo();
     boolean showConsHist = isShowConsensusHistogram();
+    boolean showSSConsHist = isShowSSConsensusHistogram();
     boolean normLogo = isNormaliseSequenceLogo();
 
     /**
@@ -2196,7 +2310,9 @@ public abstract class AlignmentViewport
         {
           // set defaults for this group's conservation/consensus
           sg.setshowSequenceLogo(showprf);
+          sg.setshowSequenceSSLogo(showSSprf);
           sg.setShowConsensusHistogram(showConsHist);
+          sg.setShowSSConsensusHistogram(showSSConsHist);
           sg.setNormaliseSequenceLogo(normLogo);
         }
         if (conv)
@@ -2208,6 +2324,7 @@ public abstract class AlignmentViewport
         {
           updateCalcs = true;
           alignment.addAnnotation(sg.getConsensus(), 0);
+          alignment.addAnnotation(sg.getSSConsensus(), 0);
         }
         // refresh the annotation rows
         if (updateCalcs)
@@ -2293,7 +2410,8 @@ public abstract class AlignmentViewport
   {
     if (this == av)
     {
-      jalview.bin.Console.errPrintln("Ignoring recursive setCodingComplement request");
+      jalview.bin.Console
+              .errPrintln("Ignoring recursive setCodingComplement request");
     }
     else
     {
@@ -2996,6 +3114,41 @@ public abstract class AlignmentViewport
             + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
     return sq;
   }
+  
+  public SequenceI getSSConsensusSeq()
+  {
+    if (secondaryStructureConsensus == null)
+    {
+      updateSecondaryStructureConsensus(null);
+    }
+    if (secondaryStructureConsensus == null)
+    {
+      return null;
+    }
+    StringBuffer seqs = new StringBuffer();
+    for (int i = 0; i < secondaryStructureConsensus.annotations.length; i++)
+    {
+      Annotation annotation = secondaryStructureConsensus.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("Sec Str Consensus", seqs.toString());
+    sq.setDescription("Percentage Identity Sec Str Consensus "
+            + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
+    return sq;
+  }
 
   @Override
   public void setCurrentTree(TreeModel tree)