JAL-4386 Added secondary structure providers check boxes in show
authorRenia Correya <rcorreya001@dundee.ac.uk>
Tue, 28 May 2024 10:13:00 +0000 (11:13 +0100)
committerRenia Correya <rcorreya001@dundee.ac.uk>
Tue, 28 May 2024 10:13:00 +0000 (11:13 +0100)
secondary structure menu. Implemented displaying of secondary structure
and consensus based on user selection. Added secondary structure
providers option in calculate window. Added provider label in pca panel
and tree panel for secondary structure similarity.

20 files changed:
resources/lang/Messages.properties
src/jalview/analysis/AAFrequency.java
src/jalview/analysis/AlignmentUtils.java
src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java
src/jalview/api/AlignViewportI.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/CalculationChooser.java
src/jalview/gui/PCAPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/TreePanel.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/project/Jalview2XML.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/ResidueShader.java
src/jalview/renderer/ResidueShaderI.java
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/workers/SecondaryStructureConsensusThread.java

index 9e68eab..3f2e633 100644 (file)
@@ -1293,7 +1293,9 @@ label.quality_descr = Alignment Quality based on Blosum62 scores
 label.conservation_descr = Conservation of total alignment less than {0}% gaps
 label.consensus_descr = PID
 label.ssconsensus_label = Secondary Structure Consensus
-label.ssconsensus_descr = SS Consensus
+label.ssconsensus_descr = Secondary Structure Consensus
+option.ss_providers_all = All
+option.ss_providers_none = None
 label.complement_consensus_descr = PID for cDNA
 label.strucconsensus_descr = PID for base pairs
 label.occupancy_descr = Number of aligned positions 
index 707110a..a979c45 100755 (executable)
@@ -196,13 +196,13 @@ public class AAFrequency
 
   
   public static final ProfilesI calculateSS(List<SequenceI> list, int start,
-          int end)
+          int end, String source)
   {
-    return calculateSS(list, start, end, false);
+    return calculateSS(list, start, end, false, source);
   }
   
   public static final ProfilesI calculateSS(List<SequenceI> sequences,
-          int start, int end, boolean profile)
+          int start, int end, boolean profile, String source)
   {
     SequenceI[] seqs = new SequenceI[sequences.size()];
     int width = 0;
@@ -222,14 +222,15 @@ public class AAFrequency
       {
         end = width;
       }
+      
 
-      ProfilesI reply = calculateSS(seqs, width, start, end, profile);
+      ProfilesI reply = calculateSS(seqs, width, start, end, profile, source);
       return reply;
     }
   }
   
   public static final ProfilesI calculateSS(final SequenceI[] sequences,
-          int width, int start, int end, boolean saveFullProfile)
+          int width, int start, int end, boolean saveFullProfile, String source)
   {
 
     int seqCount = sequences.length;
@@ -253,27 +254,31 @@ public class AAFrequency
         }
         
         char c = sequences[row].getCharAt(column);
-        AlignmentAnnotation aa = AlignmentUtils.getDisplayedAlignmentAnnotation(sequences[row]);
-        if(aa!=null) {
-          ssCount++;
-        }
-        
-        if (sequences[row].getLength() > column && !Comparison.isGap(c) && aa !=null)
-        {
-          
-          int seqPosition = sequences[row].findPosition(column);
+        List<AlignmentAnnotation> annots = AlignmentUtils.getAlignmentAnnotationForSource(sequences[row], source);
+        if(annots!=null) {
+        for(AlignmentAnnotation aa:annots) {
+          if(aa!=null) {
+            ssCount++;
+          }
           
-          char ss = AlignmentUtils.findSSAnnotationForGivenSeqposition(
-                  aa, seqPosition); 
-          if(ss == '*') {
-            continue;
-          }        
-          ssCounts.add(ss);                    
-        }
-        else if(Comparison.isGap(c) && aa!=null) {
-          ssCounts.addGap();
+          if (sequences[row].getLength() > column && !Comparison.isGap(c) && aa !=null)
+          {
+            
+            int seqPosition = sequences[row].findPosition(column);
+            
+            char ss = AlignmentUtils.findSSAnnotationForGivenSeqposition(
+                    aa, seqPosition); 
+            if(ss == '*') {
+              continue;
+            }        
+            ssCounts.add(ss);                    
+          }
+          else if(Comparison.isGap(c) && aa!=null) {
+            ssCounts.addGap();
+          }
         }
       }
+      }
 
       int maxSSCount = ssCounts.getModalCount();
       String maxSS = ssCounts.getSSForCount(maxSSCount);
index 7d0ccdb..eec982b 100644 (file)
@@ -70,6 +70,7 @@ import jalview.util.DBRefUtils;
 import jalview.util.IntRangeComparator;
 import jalview.util.MapList;
 import jalview.util.MappingUtils;
+import jalview.util.MessageManager;
 import jalview.workers.SecondaryStructureConsensusThread;
 
 /**
@@ -2854,193 +2855,302 @@ public class AlignmentUtils
   }
   
 
-  public static List<String> getSecondaryStructureSources(AlignmentAnnotation[] annotations) {
-    
-      List<String> ssSources = new ArrayList<>();
-      Set<String> addedLabels = new HashSet<>(); // to keep track of added labels
-
-      for (AlignmentAnnotation annotation : annotations) {
-          String label = annotation.label;
-          if (Constants.SECONDARY_STRUCTURE_LABELS.containsKey(label) && !addedLabels.contains(label)) {
-              ssSources.add(Constants.SECONDARY_STRUCTURE_LABELS.get(label));
-              addedLabels.add(label); // Add the label to the set
-          }
+  public static List<String> getSecondaryStructureSources(
+          AlignmentAnnotation[] annotations)
+  {
+
+    List<String> ssSources = new ArrayList<>();
+    Set<String> addedLabels = new HashSet<>(); // to keep track of added labels
+
+    for (AlignmentAnnotation annotation : annotations)
+    {
+      String label = annotation.label;
+      if (Constants.SECONDARY_STRUCTURE_LABELS.containsKey(label)
+              && !addedLabels.contains(label))
+      {
+        ssSources.add(Constants.SECONDARY_STRUCTURE_LABELS.get(label));
+        addedLabels.add(label); // Add the label to the set
       }
+    }
 
-      return ssSources;
+    return ssSources;
   }
   
   public static boolean isSecondaryStructurePresent(AlignmentAnnotation[] annotations)
   {
     boolean ssPresent = false;
-    
+
     for (AlignmentAnnotation aa : annotations)
     {
-      if(ssPresent) {
+      if (ssPresent)
+      {
         break;
-      }     
+      }
 
-      if (Constants.SECONDARY_STRUCTURE_LABELS.containsKey(aa.label)) {
-          ssPresent = true;
-          break;
+      if (Constants.SECONDARY_STRUCTURE_LABELS.containsKey(aa.label))
+      {
+        ssPresent = true;
+        break;
       }
     }
-    
+
     return ssPresent;
-    
+
   }
   
-  public static Color getSecondaryStructureAnnotationColour(char symbol){
-   
-    if (symbol== Constants.COIL) {
+  public static Color getSecondaryStructureAnnotationColour(char symbol)
+  {
+
+    if (symbol == Constants.COIL)
+    {
       return Color.gray;
     }
-    if (symbol== Constants.SHEET) {
+    if (symbol == Constants.SHEET)
+    {
       return Color.green;
     }
-    if (symbol== Constants.HELIX) {
+    if (symbol == Constants.HELIX)
+    {
       return Color.red;
     }
-    
+
     return Color.gray;
   }
 
   public static char findSSAnnotationForGivenSeqposition(AlignmentAnnotation aa,
           int seqPosition)
   {
-    char ss = '*'; 
-        
-    if (aa != null) {
-      if (aa.getAnnotationForPosition(seqPosition) != null) {
+    char ss = '*';
+
+    if (aa != null)
+    {
+      if (aa.getAnnotationForPosition(seqPosition) != null)
+      {
         Annotation a = aa.getAnnotationForPosition(seqPosition);
         ss = a.secondaryStructure;
-        
-        //There is no representation for coil and it can be either ' ' or null. 
-        if (ss == ' ' || ss == '-') {
-          ss = Constants.COIL; 
+
+        // There is no representation for coil and it can be either ' ' or null.
+        if (ss == ' ' || ss == '-')
+        {
+          ss = Constants.COIL;
         }
       }
-      else {
+      else
+      {
         ss = Constants.COIL;
-      }                 
+      }
     }
-    
-    return ss;    
+
+    return ss;
   }
   
  
-  public static List<String> extractSSSourceInAlignmentAnnotation(AlignmentAnnotation[] annotations) {
-    
+  public static List<String> extractSSSourceInAlignmentAnnotation(
+          AlignmentAnnotation[] annotations)
+  {
+
     List<String> ssSources = new ArrayList<>();
-    Set<String> addedSources = new HashSet<>(); // to keep track of added sources
+    Set<String> addedSources = new HashSet<>(); // to keep track of added
+                                                // sources
+
+    if (annotations == null)
+    {
+      return ssSources;
+    }
+
+    for (AlignmentAnnotation aa : annotations)
+    {
 
-          
-    for (AlignmentAnnotation aa: annotations) {
-      
       String ssSource = extractSSSourceFromAnnotationDescription(aa);
-      
-      if (ssSource!= null && !addedSources.contains(ssSource)) {
-          ssSources.add(ssSource);
-          addedSources.add(ssSource);
+
+      if (ssSource != null && !addedSources.contains(ssSource))
+      {
+        ssSources.add(ssSource);
+        addedSources.add(ssSource);
       }
-      
-     }
+
+    }
     Collections.sort(ssSources);
-       
+
     return ssSources;
-    
+
   }
   
-  public static String extractSSSourceFromAnnotationDescription(AlignmentAnnotation aa) {
-    
-    
-    for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) {
-      
-      if (label.equals(aa.label)) {  
-        
-        //For JPred 
-        if(aa.label.equals(Constants.SS_ANNOTATION_FROM_JPRED_LABEL)){
-          
+  public static String extractSSSourceFromAnnotationDescription(
+          AlignmentAnnotation aa)
+  {
+
+    for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet())
+    {
+
+      if (label.equals(aa.label))
+      {
+
+        // For JPred
+        if (aa.label.equals(Constants.SS_ANNOTATION_FROM_JPRED_LABEL))
+        {
+
           return (Constants.SECONDARY_STRUCTURE_LABELS.get(aa.label));
-          
-         }
-        
-        //For input with secondary structure
-        if(aa.label.equals(Constants.SS_ANNOTATION_LABEL) 
-                && aa.description.equals(Constants.SS_ANNOTATION_LABEL)){
-          
+
+        }
+
+        // For input with secondary structure
+        if (aa.label.equals(Constants.SS_ANNOTATION_LABEL)
+                && aa.description.equals(Constants.SS_ANNOTATION_LABEL))
+        {
+
           return (Constants.SECONDARY_STRUCTURE_LABELS.get(aa.label));
-          
-         }
-        
-        //For other sources
-        if(aa.sequenceRef==null) {
+
+        }
+
+        // For other sources
+        if (aa.sequenceRef == null)
+        {
           return null;
         }
-        else if(aa.sequenceRef.getDatasetSequence()==null) {
+        else if (aa.sequenceRef.getDatasetSequence() == null)
+        {
           return null;
         }
-         Vector<PDBEntry> pdbEntries = aa.sequenceRef.getDatasetSequence().getAllPDBEntries();
-         
-         for (PDBEntry entry : pdbEntries){
-           
-           String entryProvider = entry.getProvider();
-           if(entryProvider == null) {
-             entryProvider = "PDB";
-           }
-           
-           // Trim the string from first occurrence of colon
-           String entryID = entry.getId();
-           int index = entryID.indexOf(':');
-           
-           // Check if colon exists
-           if (index != -1) {
-             
-             // Trim the string from first occurrence of colon
-             entryID = entryID.substring(0, index); 
-             
-           }
-           
-           if(entryProvider == "PDB" && aa.description.toLowerCase().contains
-                     ("secondary structure for " + entryID.toLowerCase())){
-               
-               return entryProvider;
-             
-           }
-           
-           else if (entryProvider != "PDB" && aa.description.toLowerCase().contains(entryID.toLowerCase())){
-              
-              return entryProvider;
-            
-            }
-          
+        Vector<PDBEntry> pdbEntries = aa.sequenceRef.getDatasetSequence()
+                .getAllPDBEntries();
+
+        for (PDBEntry entry : pdbEntries)
+        {
+
+          String entryProvider = entry.getProvider();
+          if (entryProvider == null)
+          {
+            entryProvider = "PDB";
+          }
+
+          // Trim the string from first occurrence of colon
+          String entryID = entry.getId();
+          int index = entryID.indexOf(':');
+
+          // Check if colon exists
+          if (index != -1)
+          {
+
+            // Trim the string from first occurrence of colon
+            entryID = entryID.substring(0, index);
+
+          }
+
+          if (entryProvider == "PDB" && aa.description.toLowerCase()
+                  .contains("secondary structure for "
+                          + entryID.toLowerCase()))
+          {
+
+            return entryProvider;
+
+          }
+
+          else if (entryProvider != "PDB" && aa.description.toLowerCase()
+                  .contains(entryID.toLowerCase()))
+          {
+
+            return entryProvider;
+
           }
-          
-        }   
+
+        }
       }
-    
+    }
+
     return null;
-    
+
   }
   
   //to do set priority for labels
-  public static AlignmentAnnotation getDisplayedAlignmentAnnotation(SequenceI seq){
-    
-    for(String ssLabel : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) {
-    
-    AlignmentAnnotation[] aa = seq.getAnnotation(ssLabel);
-    if(aa!=null) {
-      
-      for (AlignmentAnnotation annot: aa) {
-        if(annot.visible) {
-          return annot;
+  public static List<AlignmentAnnotation> getAlignmentAnnotationForSource(
+          SequenceI seq, String ssSource)
+  {
+
+    List<AlignmentAnnotation> ssAnnots = new ArrayList<AlignmentAnnotation>();
+    for (String ssLabel : Constants.SECONDARY_STRUCTURE_LABELS.keySet())
+    {
+
+      AlignmentAnnotation[] aa = seq.getAnnotation(ssLabel);
+      if (aa != null)
+      {
+
+        if (ssSource.equals(MessageManager.getString("option.ss_providers_all")))
+        {
+          ssAnnots.addAll(Arrays.asList(aa));
+          continue;
+        }
+
+        for (AlignmentAnnotation annot : aa)
+        {
+
+          if (ssSource
+                  .equals(extractSSSourceFromAnnotationDescription(annot)))
+          {
+            ssAnnots.add(annot);
+          }
         }
       }
-     }
     }
-    
+    if (ssAnnots.size() > 0)
+    {
+      return ssAnnots;
+    }
+
     return null;
-    
+
+  }
+
+  public static Map<SequenceI, ArrayList<AlignmentAnnotation>> getSequenceAssociatedAlignmentAnnotations(
+          AlignmentAnnotation[] alignAnnotList, String selectedSSSource)
+  {
+
+    Map<SequenceI, ArrayList<AlignmentAnnotation>> ssAlignmentAnnotationForSequences 
+             = new HashMap<SequenceI, ArrayList<AlignmentAnnotation>>();
+    if (alignAnnotList == null || alignAnnotList.length == 0)
+    {
+      return ssAlignmentAnnotationForSequences;
+    }
+
+    for (AlignmentAnnotation aa : alignAnnotList)
+    {
+      if (aa.sequenceRef == null)
+      {
+        continue;
+      }
+      
+      for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet())
+      {
+
+        if (label.equals(aa.label))
+        {
+
+          if (selectedSSSource.equals(MessageManager.getString("option.ss_providers_all")))
+          {
+            ssAlignmentAnnotationForSequences
+                    .computeIfAbsent(aa.sequenceRef.getDatasetSequence(),
+                            k -> new ArrayList<>())
+                    .add(aa);
+            break;
+          }
+
+          String ssSource = AlignmentUtils
+                  .extractSSSourceFromAnnotationDescription(aa);
+          if (ssSource.equals(selectedSSSource))
+          {
+
+            ssAlignmentAnnotationForSequences
+                    .computeIfAbsent(aa.sequenceRef.getDatasetSequence(),
+                            k -> new ArrayList<>())
+                    .add(aa);
+            break;
+          }
+        }
+      }
+    }
+
+    return ssAlignmentAnnotationForSequences;
+
   }
   
 }
index 6cce5b4..4e3a3de 100644 (file)
@@ -27,14 +27,13 @@ import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.SimilarityParamsI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentView;
-import jalview.datamodel.Annotation;
 import jalview.datamodel.SeqCigar;
+import jalview.datamodel.SequenceI;
 import jalview.math.Matrix;
 import jalview.math.MatrixI;
-import jalview.util.Constants;
-import jalview.util.SetUtils;
+import jalview.util.MessageManager;
 
-import java.util.HashMap;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
@@ -110,53 +109,29 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
     
     SeqCigar[] seqs = seqData.getSequences();
     int noseqs = seqs.length; //no of sequences
-    int cpwidth = 0; // = seqData.getWidth();
+    int cpwidth = 0; 
     double[][] similarities = new double[noseqs][noseqs]; //matrix to store similarity score
     //secondary structure source parameter selected by the user from the drop down.
     String ssSource = params.getSecondaryStructureSource(); 
-    ssRateMatrix = ScoreModels.getInstance().getSecondaryStructureMatrix();
-    
-    //defining the default value for secondary structure source as 3d structures 
-    //or JPred if user selected JPred
-    String selectedSSSource = Constants.SS_ANNOTATION_LABEL;
-    if(ssSource.equals(Constants.SECONDARY_STRUCTURE_LABELS.get(Constants.SS_ANNOTATION_FROM_JPRED_LABEL)))
-    {
-      selectedSSSource = Constants.SS_ANNOTATION_FROM_JPRED_LABEL;
+    if(ssSource == null || ssSource == "") {
+      ssSource = MessageManager.getString("option.ss_providers_all");
     }
+    ssRateMatrix = ScoreModels.getInstance().getSecondaryStructureMatrix();
         
     // need to get real position for view position
     int[] viscont = seqData.getVisibleContigs();
     
-    /*
-     * Add secondary structure annotations that are added to the annotation track
-     * to the map
-     */
-    Map<String, HashSet<String>> ssAlignmentAnnotationForSequences 
-      = new HashMap<String,HashSet<String>>();    
     
     AlignmentAnnotation[] alignAnnotList = fr.getViewport().getAlignment()
             .getAlignmentAnnotation();   
     
-    if(alignAnnotList.length > 0) {      
-      for (AlignmentAnnotation aa: alignAnnotList) {
-        if (selectedSSSource.equals(aa.label)) {          
-          ssAlignmentAnnotationForSequences.computeIfAbsent(
-                  aa.sequenceRef.getName(), k -> new HashSet<>())
-          .add(aa.description);
-        }        
-      }      
-    }
-    
+
     /*
-     * Get the set of sequences which are not considered for the calculation.
-     * Following sequences are added:
-     * 1. Sequences without a defined secondary structure from the selected 
-     * source.
-     * 2. Sequences whose secondary structure annotations are not added to 
-     * the annotation track
+     * Add secondary structure annotations that are added to the annotation track
+     * to the map
      */
-    Set<SeqCigar> seqsWithUndefinedSS 
-        = findSeqsWithUndefinedSS(seqs, ssAlignmentAnnotationForSequences);
+    Map<SequenceI, ArrayList<AlignmentAnnotation>> ssAlignmentAnnotationForSequences 
+      = AlignmentUtils.getSequenceAssociatedAlignmentAnnotations(alignAnnotList, ssSource); 
 
     /*
      * scan each column, compute and add to each similarity[i, j]
@@ -185,13 +160,10 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
           //Iterates for each sequences
           for (int j = i + 1; j < noseqs; j++)
           {
-            SeqCigar sc1 = seqs[i];
-            SeqCigar sc2 = seqs[j];
                          
-
             //check if ss is defined
-            boolean undefinedSS1 = seqsWithUndefinedSS.contains(sc1);
-            boolean undefinedSS2 = seqsWithUndefinedSS.contains(sc2);
+            boolean undefinedSS1 = ssAlignmentAnnotationForSequences.get(seqs[i].getRefSeq()) == null;
+            boolean undefinedSS2 = ssAlignmentAnnotationForSequences.get(seqs[j].getRefSeq()) == null;
 
             // Set similarity to max score if both SS are not defined
             if (undefinedSS1 && undefinedSS2) {
@@ -206,8 +178,8 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
             }
             
             //check if the sequence contains gap in the current column
-            boolean gap1 = !seqsWithoutGapAtCol.contains(sc1);
-            boolean gap2 = !seqsWithoutGapAtCol.contains(sc2);            
+            boolean gap1 = !seqsWithoutGapAtCol.contains(seqs[i]);
+            boolean gap2 = !seqsWithoutGapAtCol.contains(seqs[j]);            
             
             //Variable to store secondary structure at the current column
             char ss1 = '*';
@@ -220,18 +192,18 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
               //corresponding secondary structure annotation
               //TO DO - consider based on priority and displayed
               int seqPosition = seqs[i].findPosition(cpos);
-              AlignmentAnnotation[] aa = seqs[i].getRefSeq().getAnnotation(selectedSSSource);
+              AlignmentAnnotation aa = ssAlignmentAnnotationForSequences.get(seqs[i].getRefSeq()).get(0);
               if(aa!=null)
               ss1 = 
-                  AlignmentUtils.findSSAnnotationForGivenSeqposition(aa[0], seqPosition);              
+                  AlignmentUtils.findSSAnnotationForGivenSeqposition(aa, seqPosition);              
             }
             
             if(!gap2 && !undefinedSS2) {              
               int seqPosition = seqs[j].findPosition(cpos);
-              AlignmentAnnotation[] aa = seqs[j].getRefSeq().getAnnotation(selectedSSSource);
+              AlignmentAnnotation aa = ssAlignmentAnnotationForSequences.get(seqs[j].getRefSeq()).get(0);
               if(aa!=null)
                 ss2 = 
-                  AlignmentUtils.findSSAnnotationForGivenSeqposition(aa[0], seqPosition);               
+                  AlignmentUtils.findSSAnnotationForGivenSeqposition(aa, seqPosition);               
             }           
 
             if ((!gap1 && !gap2) || params.includeGaps())
@@ -291,65 +263,6 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
     return seqsWithoutGapAtCol;
   }
 
-  
-  /**
-   * Builds and returns a set containing sequences (SeqCigar) which
-   * are not considered for the similarity calculation.
-   * Following sequences are added:
-   * 1. Sequences without a defined secondary structure from the selected 
-   * source.
-   * 2. Sequences whose secondary structure annotations are not added to 
-   * the annotation track
-   * @param seqs
-   * @param ssAlignmentAnnotationForSequences         
-   * @return
-   */
-  private Set<SeqCigar> findSeqsWithUndefinedSS(SeqCigar[] seqs,
-          Map<String, HashSet<String>> ssAlignmentAnnotationForSequences) {
-      Set<SeqCigar> seqsWithUndefinedSS = new HashSet<>();
-      for (SeqCigar seq : seqs) {
-          if (isSSUndefinedOrNotAdded(seq, ssAlignmentAnnotationForSequences)) {
-              seqsWithUndefinedSS.add(seq);
-          }
-      }
-      return seqsWithUndefinedSS;
-  }
-  
-  
-  /**
-   * Returns true if a sequence (SeqCigar) should not be
-   * considered for the similarity calculation.
-   * Following conditions are checked:
-   * 1. Sequence without a defined secondary structure from the selected 
-   * source.
-   * 2. Sequences whose secondary structure annotations are not added to 
-   * the annotation track
-   * @param seq
-   * @param ssAlignmentAnnotationForSequences
-   * @return
-   */
-  private boolean isSSUndefinedOrNotAdded(SeqCigar seq, 
-          Map<String, HashSet<String>> ssAlignmentAnnotationForSequences) {
-      for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) {
-          AlignmentAnnotation[] annotations = seq.getRefSeq().getAnnotation(label);
-          if (annotations != null) {
-              for (AlignmentAnnotation annotation : annotations) {                
-                HashSet<String> descriptionSet = ssAlignmentAnnotationForSequences
-                        .get(annotation.sequenceRef.getName());
-                if (descriptionSet != null)
-                {
-                  if (descriptionSet.contains(annotation.description)) {
-                      // Secondary structure annotation is present and 
-                      //added to the track, no need to add seq
-                      return false;
-                  }
-                }
-              }
-          }
-      }
-      // Either annotations are undefined or not added to the track
-      return true;
-  }
     
   @Override
   public String getName()
index b7747f5..404d8ea 100644 (file)
@@ -134,7 +134,7 @@ public interface AlignViewportI extends ViewStyleI
    */
   AlignmentAnnotation getAlignmentConsensusAnnotation();
   
-  AlignmentAnnotation getAlignmentSecondaryStructureConsensusAnnotation();
+  List<AlignmentAnnotation> getAlignmentSecondaryStructureConsensusAnnotation();
 
 
   /**
@@ -183,7 +183,7 @@ public interface AlignViewportI extends ViewStyleI
    */
   void setSequenceConsensusHash(ProfilesI hconsensus);
   
-  void setSequenceSSConsensusHash(ProfilesI hSSConsensus);
+  void setSequenceSSConsensusHash(Map<String, ProfilesI> hSSConsesnusProfileMap);
   
 
   /**
@@ -578,6 +578,10 @@ public interface AlignViewportI extends ViewStyleI
 
   ContactMatrixI getContactMatrix(AlignmentAnnotation alignmentAnnotation);
 
-  ProfilesI getSequenceSSConsensusHash();
+  Map<String, ProfilesI> getSequenceSSConsensusHash();
+
+  List<String> getSecondaryStructureSources();
+
+  void setSecondaryStructureSources(List<String> secondaryStructureSources);
 
 }
index 73ccdc5..ce9250c 100755 (executable)
@@ -71,6 +71,8 @@ public class Alignment implements AlignmentI, AutoCloseable
   public Hashtable alignmentProperties;
 
   private List<AlignedCodonFrame> codonFrameList;
+  
+  private List<String> secondaryStructureSources;
 
   private void initAlignment(SequenceI[] seqs)
   {
@@ -82,12 +84,13 @@ public class Alignment implements AlignmentI, AutoCloseable
     nucleotide = Comparison.isNucleotide(seqs);
 
     sequences = Collections.synchronizedList(new ArrayList<SequenceI>());
+    
 
     for (int i = 0; i < seqs.length; i++)
     {
       sequences.add(seqs[i]);
     }
-
+   
   }
 
   /**
@@ -2122,4 +2125,16 @@ public class Alignment implements AlignmentI, AutoCloseable
     cmholder.addContactListFor(annotation, cm);
 
   }
+
+  public List<String> getSecondaryStructureSources()
+  {
+    return secondaryStructureSources;
+  }
+
+  public void setSecondaryStructureSources(
+          List<String> secondaryStructureSources)
+  {
+    this.secondaryStructureSources = secondaryStructureSources;
+  }
+
 }
index b5048a0..5416ac4 100755 (executable)
@@ -26,6 +26,8 @@ import java.beans.PropertyChangeSupport;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -34,6 +36,7 @@ import jalview.analysis.Conservation;
 import jalview.renderer.ResidueShader;
 import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
+import jalview.util.MessageManager;
 
 /**
  * Collects a set contiguous ranges on a set of sequences
@@ -154,7 +157,7 @@ public class SequenceGroup implements AnnotatedCollectionI
   AlignmentAnnotation consensus = null;
   
 
-  AlignmentAnnotation ssConsensus = null;
+  List<AlignmentAnnotation> ssConsensus = null;
 
   AlignmentAnnotation conservation = null;
 
@@ -619,18 +622,31 @@ public class SequenceGroup implements AnnotatedCollectionI
         cs.setConsensus(cnsns);
         upd = true;
       }
+
+      Map<String, ProfilesI> hSSConsensusProfileMap = new HashMap<String, ProfilesI>();
+      List <String> ssSources = new ArrayList<String>();
       
-      
-      ProfilesI ssCnsns = AAFrequency.calculateSS(sequences, startRes,
-              endRes + 1, showSequenceLogo);
+        //ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(ssConsensus.toArray());
+      if(ssSources != null) {
+        ssSources.add(MessageManager.getString("option.ss_providers_all"));
+
+        for(String ssSource : ssSources) {
+          ProfilesI hSSConsensus = AAFrequency.calculateSS(sequences, startRes,  endRes + 1, showSequenceLogo,
+                  ssSource);
+          hSSConsensusProfileMap.put(ssSource, hSSConsensus);
+        }
+      }
+            
+
       if (ssConsensus != null)
       {
-        _updateSSConsensusRow(ssCnsns, sequences.size());
+        _updateSSConsensusRow(hSSConsensusProfileMap, sequences.size());
         upd = true;
       }
+      
       if (cs != null)
       {
-        cs.setSsConsensus(ssCnsns);
+        cs.setSSConsensusProfileMap(hSSConsensusProfileMap);
         upd = true;
       }
       
@@ -726,27 +742,44 @@ public class SequenceGroup implements AnnotatedCollectionI
   
   public ProfilesI ssConsensusData = null;
   
-  private void _updateSSConsensusRow(ProfilesI ssCnsns, long nseq)
+  private void _updateSSConsensusRow(Map<String, ProfilesI> hSSConsensusProfileMap, long nseq)
   {
+    List<String> ssSources = new ArrayList<>(hSSConsensusProfileMap.keySet());
+
+    Collections.sort(ssSources);
     if (ssConsensus == null)
     {
-      getSSConsensus();
+      getSSConsensus(ssSources);
     }
-    ssConsensus.label = "Sec Str Consensus for " + getName();
-    ssConsensus.description = "Percent Identity";
-    ssConsensusData = ssCnsns;
-    // preserve width if already set
-    int aWidth = (ssConsensus.annotations != null)
-            ? (endRes < ssConsensus.annotations.length
-                    ? ssConsensus.annotations.length
-                    : endRes + 1)
-            : endRes + 1;
-    ssConsensus.annotations = null;
-    ssConsensus.annotations = new Annotation[aWidth]; // should be alignment width
+    for (AlignmentAnnotation aa : ssConsensus) {
+      ProfilesI profile = null;
+      String ssSource = null;
+      for(String source : ssSources) {
+        if(aa.description.startsWith(source)) {
+          profile = hSSConsensusProfileMap.get(source);
+          ssSource = source;
+        }
+      }
+      if(profile == null) {
+        continue;
+      }
 
-    AAFrequency.completeSSConsensus(ssConsensus, ssCnsns, startRes, endRes + 1,
+      aa.label = MessageManager.getString("label.ssconsensus_label") + " " + ssSource + " " + getName();
+      aa.description = ssSource + MessageManager.getString("label.ssconsensus_label") +" for " + getName();
+      ssConsensusData = profile;
+      // preserve width if already set
+      int aWidth = (aa.annotations != null)
+              ? (endRes < aa.annotations.length
+                      ? aa.annotations.length
+                      : endRes + 1)
+              : endRes + 1;
+      aa.annotations = null;
+      aa.annotations = new Annotation[aWidth]; // should be alignment width
+    
+    AAFrequency.completeSSConsensus(aa, profile, startRes, endRes + 1,
             ignoreGapsInConsensus, showSequenceLogo, nseq); // TODO: setting
                                                             // container
+    }
     // for
     // ignoreGapsInConsensusCalculation);
   }
@@ -1206,7 +1239,7 @@ public class SequenceGroup implements AnnotatedCollectionI
     return consensus;
   }
   
-  public AlignmentAnnotation getSSConsensus()
+  public List<AlignmentAnnotation> getSSConsensus(List<String> ssSources)
   {
     // TODO get or calculate and get consensus annotation row for this group
     int aWidth = this.getWidth();
@@ -1219,13 +1252,20 @@ public class SequenceGroup implements AnnotatedCollectionI
     }
     if (ssConsensus == null)
     {
-      ssConsensus = new AlignmentAnnotation("", "", new Annotation[1], 0f,
-              100f, AlignmentAnnotation.BAR_GRAPH);
-      ssConsensus.hasText = true;
-      ssConsensus.autoCalculated = true;
-      ssConsensus.groupRef = this;
-      ssConsensus.label = "Sec Str Consensus for " + getName();
-      ssConsensus.description = "Percent Identity";
+      ssConsensus = new ArrayList<AlignmentAnnotation>();
+      
+      for(String ssSource : ssSources) {
+        AlignmentAnnotation aa = new AlignmentAnnotation("", "", new Annotation[1], 0f,
+                100f, AlignmentAnnotation.BAR_GRAPH);
+        aa.hasText = true;
+        aa.autoCalculated = true;
+        aa.groupRef = this;
+
+        aa.label = MessageManager.getString("label.ssconsensus_label") + " " + ssSource + " " + getName();
+        aa.description = ssSource + MessageManager.getString("label.ssconsensus_label") +" for " + getName();
+        ssConsensus.add(aa);
+      }
+     
     }
     return ssConsensus;
   }
index ccda002..45bfe83 100644 (file)
@@ -56,14 +56,14 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Deque;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Vector;
 
-import javax.swing.AbstractButton;
 import javax.swing.ButtonGroup;
-import javax.swing.ButtonModel;
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JComponent;
 import javax.swing.JEditorPane;
@@ -73,7 +73,6 @@ import javax.swing.JLayeredPane;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
-import javax.swing.JRadioButtonMenuItem;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
 
@@ -85,7 +84,6 @@ import jalview.analysis.Dna;
 import jalview.analysis.GeneticCodeI;
 import jalview.analysis.ParseProperties;
 import jalview.analysis.SequenceIdMatcher;
-import jalview.api.AlignCalcWorkerI;
 import jalview.api.AlignExportSettingsI;
 import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
@@ -162,7 +160,6 @@ import jalview.util.Platform;
 import jalview.util.imagemaker.BitmapImageSizing;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.ViewportRanges;
-import jalview.workers.SecondaryStructureConsensusThread;
 import jalview.ws.DBRefFetcher;
 import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
 import jalview.ws.jws1.Discoverer;
@@ -5683,131 +5680,111 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
   
   @Override
-  protected void updateShowSSRadioButtons(JMenu showSS, ButtonGroup ssButtonGroup){
+  protected void updateShowSecondaryStructureMenu(JMenu showSS, ButtonGroup ssButtonGroup){
     
     List<String> ssSources = new ArrayList<String>();
     AlignmentAnnotation[] anns = alignPanel.getAlignment()
             .getAlignmentAnnotation();
+    Map<String, JCheckBoxMenuItem> checkboxMap = getCheckboxesInMenu(showSS);
     
     ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(anns);
     
-    // Get the currently selected radio button
-    String selectedButtonModelName = getSelectedRadioButtonDisplayString(ssButtonGroup);
-    boolean selectedButtonModel =  false;
+    List<String> selectedCheckBoxes = getSelectedOptions(checkboxMap);
     
-    // Clear existing radio buttons
-    showSS.removeAll();
-    JRadioButtonMenuItem radioButtonAllSS = new JRadioButtonMenuItem("All");
-    radioButtonAllSS.addActionListener(new ActionListener() {
-      @Override
-      public void actionPerformed(ActionEvent e) {
-          showSS_actionPerformed("All");
-      }
-    });
-    ssButtonGroup.add(radioButtonAllSS);
-    showSS.add(radioButtonAllSS);
-    
-    JRadioButtonMenuItem radioButtonNoneSS = new JRadioButtonMenuItem("None");
-    radioButtonNoneSS.addActionListener(new ActionListener() {
-      @Override
-      public void actionPerformed(ActionEvent e) {
-          showSS_actionPerformed("None");
+    // Add checkboxes for categories
+    for (String ssSource : ssSources) {
+      
+      if(checkboxMap.get(ssSource)== null) {
+        JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem(ssSource);
+        checkBox.setSelected(false);
+                
+        checkBox.addItemListener(e -> {
+            if (e.getStateChange() == ItemEvent.SELECTED) {
+                
+              showOrHideSecondaryStructureForSource(ssSource, true);
+              
+            } else {
+                
+
+              showOrHideSecondaryStructureForSource(ssSource, false);
+            }
+        });
+        showSS.add(checkBox);
       }
-    });
-    ssButtonGroup.add(radioButtonNoneSS);
-    showSS.add(radioButtonNoneSS);
-    showSS.addSeparator();
+    }
+    // Iterate over the keys of checkboxMap
+    for (String key : checkboxMap.keySet()) {
+        // Check if the key is not in ssSources
+        if (!ssSources.contains(key)) {
+            showSS.remove(checkboxMap.get(key));            
+            checkboxMap.remove(key);
+            selectedCheckBoxes.remove(key);
+        }
+        if(selectedCheckBoxes.contains(key)){
+          checkboxMap.get(key).setSelected(true);
+        }
+        else {
+          checkboxMap.get(key).setSelected(false);
+        }        
 
-       for(String ssSource : ssSources) {
-        
-        JRadioButtonMenuItem radioButton = new JRadioButtonMenuItem(ssSource);
-        radioButton.addActionListener(new ActionListener() {
-          @Override
-          public void actionPerformed(ActionEvent e) {
-              showSS_actionPerformed(ssSource);
-          }
-        });
-        ssButtonGroup.add(radioButton);
-        showSS.add(radioButton);
-        
-        // Check if this radio button's name matches the selected radio button's name
-        if (ssSource.equals(selectedButtonModelName)) {
-            radioButton.setSelected(true); // Select this radio button
-            selectedButtonModel = true;
+        ssButtonGroup.clearSelection();
+    }
+
+  }
+  
+  private List<String> getSelectedOptions(Map<String, JCheckBoxMenuItem> checkboxMap) {
+    List<String> selectedOptions = new ArrayList<>();
+    for (String key : checkboxMap.keySet()) {
+        JCheckBoxMenuItem checkbox = checkboxMap.get(key);
+        if (checkbox.isSelected()) {
+            selectedOptions.add(key);
         }
-        
-      } 
-
-       if (selectedButtonModelName == "None") {
-         // If no radio button was previously selected, select "All"
-         ssButtonGroup.setSelected(radioButtonNoneSS.getModel(), true);
-         selectedButtonModel = true;
-       }
-       if (!selectedButtonModel) {
-           // If no radio button was previously selected, select "All"
-           ssButtonGroup.setSelected(radioButtonAllSS.getModel(), true);
-       }
+    }
+    return selectedOptions;
   }
   
-  @Override
-  protected void showSS_actionPerformed(String ssSourceSelection){
+  private Map<String, JCheckBoxMenuItem> getCheckboxesInMenu(JMenu menu) {
+    Map<String, JCheckBoxMenuItem> checkboxMap = new HashMap<>();
+    for (Component component : menu.getMenuComponents()) {
+        if (component instanceof JCheckBoxMenuItem) {
+            JCheckBoxMenuItem checkbox = (JCheckBoxMenuItem) component;
+            checkboxMap.put(checkbox.getText(), checkbox);
+        }
+    }
+    return checkboxMap;
+}
+  
+  
+  protected void showOrHideSecondaryStructureForSource(String ssSourceSelection, boolean visible){
     
-
     AlignmentAnnotation[] annotations = alignPanel.getAlignment()
             .getAlignmentAnnotation();
     
     for (AlignmentAnnotation aa: annotations) {
       
+      if(aa.label.startsWith(MessageManager.getString("label.ssconsensus_label")) && aa.description.startsWith(ssSourceSelection)) {
+        aa.visible  = visible;
+      }
+      
       for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) {
         
         if (label.equals(aa.label)) { 
-          
-          aa.visible = false;
-          
-          if(ssSourceSelection == "All") {
-            aa.visible = true;
-          }
-          
-          else {
+
             String ssSource = AlignmentUtils.extractSSSourceFromAnnotationDescription(aa);
             if(ssSource.equals(ssSourceSelection)) {
-              aa.visible = true;
-            }
-            
-            
-          }
+              aa.visible = visible;
+            }           
         }
       }
       
     }
     
-      
-      List<AlignCalcWorkerI> workers = viewport.getCalcManager()
-              .getRegisteredWorkersOfClass(SecondaryStructureConsensusThread.class);
-      if (!workers.isEmpty()) {
-          
-        viewport.getCalcManager().startWorker(workers.remove(0));
-
-      }
-      
       PaintRefresher.Refresh(this, viewport.getSequenceSetId());
       alignPanel.updateAnnotation();
       alignPanel.paintAlignment(true, true);
-          
-    
     
   }
-  
-  protected String getSelectedRadioButtonDisplayString(ButtonGroup ssButtonGroup) {
-    Enumeration<AbstractButton> buttons = ssButtonGroup.getElements();
-    while (buttons.hasMoreElements()) {
-        AbstractButton button = buttons.nextElement();
-        if (button.isSelected()) {
-            return button.getText();
-        }
-    }
-    return null; // No radio button is selected
-}
+
 
   /*
    * (non-Javadoc)
index 4e1fcab..756a266 100644 (file)
@@ -318,7 +318,7 @@ public class AlignViewport extends AlignmentViewport
     if (residueShading != null)
     {
       residueShading.setConsensus(hconsensus);
-      residueShading.setSsConsensus(hSSConsensus);
+      residueShading.setSSConsensusProfileMap(hSSConsensusProfileMap);
     }
     setColourAppliesToAllGroups(true);
   }
index 4e22a74..8c8bf21 100644 (file)
@@ -312,7 +312,7 @@ public class CalculationChooser extends JPanel
     }
     this.add(actionPanel, BorderLayout.SOUTH);
 
-    int width = 365;
+    int width = 375;
     int height = includeParams ? 420 : 240;
 
     setMinimumSize(new Dimension(325, height - 10));
@@ -467,8 +467,13 @@ public class CalculationChooser extends JPanel
     final JComboBox<String> comboBox = new JComboBox<>();
     Object curSel = comboBox.getSelectedItem();
     DefaultComboBoxModel<String> sourcesModel = new DefaultComboBoxModel<>();
-
+    
     List<String> ssSources = getApplicableSecondaryStructureSources();
+    
+    if(ssSources == null) {
+      return comboBox;
+    }
+    ssSources.add(0, MessageManager.getString("option.ss_providers_all")); 
 
     boolean selectedIsPresent = false;
     for (String source : ssSources)
@@ -593,8 +598,8 @@ public class CalculationChooser extends JPanel
   {
     AlignmentAnnotation[] annotations = af.getViewport().getAlignment().getAlignmentAnnotation();
     
-    List<String> ssSources = AlignmentUtils.getSecondaryStructureSources(annotations);
-    //List<String> ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(annotations);
+    //List<String> ssSources = AlignmentUtils.getSecondaryStructureSources(annotations);
+    List<String> ssSources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(annotations);
     
                  
     return ssSources;
@@ -607,16 +612,18 @@ public class CalculationChooser extends JPanel
   {
     boolean doPCA = pca.isSelected();
     String modelName = modelNames.getSelectedItem().toString();
-    String ssSource = "";
-    Object selectedItem = ssSourceDropdown.getSelectedItem();
-    if (selectedItem != null) {
-        ssSource = selectedItem.toString();
+
+    String ssSource = null;
+    
+    if (modelName.equals(secondaryStructureModelName)) {
+      Object selectedItem = ssSourceDropdown.getSelectedItem();
+      if (selectedItem != null) {
+          ssSource = selectedItem.toString();
+      }
     }
     SimilarityParams params = getSimilarityParameters(doPCA);
-    if(ssSource.length()>0)
-    {
-      params.setSecondaryStructureSource(ssSource);
-    }
+    params.setSecondaryStructureSource(ssSource);
+    
     if (doPCA)
     {
       openPcaPanel(modelName, params);
index 576f3b2..0bcb0da 100644 (file)
@@ -32,8 +32,10 @@ import java.awt.print.PrinterException;
 import java.awt.print.PrinterJob;
 
 import javax.swing.ButtonGroup;
+import javax.swing.JLabel;
 import javax.swing.JMenuItem;
 import javax.swing.JRadioButtonMenuItem;
+import javax.swing.SwingConstants;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
 
@@ -129,6 +131,14 @@ public class PCAPanel extends GPCAPanel
     PaintRefresher.Register(this, av.getSequenceSetId());
 
     setRotatableCanvas(new RotatableCanvas(alignPanel));
+
+    if(params.getSecondaryStructureSource()!=null ) {
+      // Initialize and set subtitle text
+      JLabel subtitleLabel = new JLabel(" Secondary Structure Provider : " 
+                  + params.getSecondaryStructureSource(), SwingConstants.LEFT);
+      this.getContentPane().add(subtitleLabel, BorderLayout.NORTH); 
+    
+    }
     this.getContentPane().add(getRotatableCanvas(), BorderLayout.CENTER);
 
     addKeyListener(getRotatableCanvas());
index d2c00eb..d1eeb73 100644 (file)
@@ -1741,10 +1741,16 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
     AlignmentUtils.addReferenceAnnotations(candidates, alignment, null);
         
     if(AlignmentUtils.isSSAnnotationPresent(candidates)) {
+      
       restartSSConsensusWorker();
+      ap.validateAnnotationDimensions(true);
+      ap.fontChanged();
+      ap.av.alignmentChanged(ap);
+      ap.adjustAnnotationHeight();
+      restartSSConsensusWorker();
+      //ap.alignFrame.getViewport().getCalcManager().restartWorkers();
     }
         
-    refresh();
   }
   
   
index f708c48..a421850 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import java.awt.BorderLayout;
 import java.awt.Font;
 import java.awt.Graphics;
 import java.awt.event.ActionEvent;
@@ -35,8 +36,11 @@ import java.util.List;
 import java.util.Locale;
 
 import javax.swing.ButtonGroup;
+import javax.swing.JLabel;
 import javax.swing.JMenuItem;
+import javax.swing.JPanel;
 import javax.swing.JRadioButtonMenuItem;
+import javax.swing.SwingConstants;
 import javax.swing.event.InternalFrameAdapter;
 import javax.swing.event.InternalFrameEvent;
 
@@ -96,6 +100,10 @@ public class TreePanel extends GTreePanel
   TreeModel tree;
 
   private AlignViewport av;
+  
+
+  // New JLabel for subtitle
+  private JLabel subtitleLabel;
 
   /**
    * Creates a new TreePanel object.
@@ -181,6 +189,20 @@ public class TreePanel extends GTreePanel
 
     treeCanvas = new TreeCanvas(this, ap, scrollPane);
     scrollPane.setViewportView(treeCanvas);
+    
+    if(this.similarityParams.getSecondaryStructureSource()!=null ) {
+    
+      // Initialize the subtitle label
+      subtitleLabel = new JLabel(" Secondary Structure Provider : " 
+                + this.similarityParams.getSecondaryStructureSource(), SwingConstants.LEFT);
+  
+      // Create a new panel to hold the label and treeCanvas
+      JPanel panel = new JPanel(new BorderLayout());
+      panel.add(subtitleLabel, BorderLayout.NORTH);
+      panel.add(scrollPane, BorderLayout.CENTER);
+  
+      this.add(panel);
+    }
 
     if (columnWise)
     {
index 3c9f642..f02f204 100755 (executable)
@@ -22,8 +22,8 @@ package jalview.jbgui;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Component;
 import java.awt.GridLayout;
-import java.awt.Menu;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.FocusAdapter;
@@ -56,13 +56,10 @@ import jalview.analysis.GeneticCodeI;
 import jalview.analysis.GeneticCodes;
 import jalview.api.SplitContainerI;
 import jalview.bin.Cache;
-import jalview.bin.Console;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.Preferences;
 import jalview.io.FileFormats;
-import jalview.log.JLoggerLog4j;
 import jalview.schemes.ResidueColourScheme;
-import jalview.util.Log4j;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 
@@ -199,10 +196,6 @@ public class GAlignFrame extends JInternalFrame
 
   protected JMenuItem expandViews = new JMenuItem();
   
-  protected JCheckBoxMenuItem threeDStructure = new JCheckBoxMenuItem();
-
-  protected JCheckBoxMenuItem jPred = new JCheckBoxMenuItem();
-
   protected JCheckBoxMenuItem showGroupConsensus = new JCheckBoxMenuItem();
 
   protected JCheckBoxMenuItem showGroupConservation = new JCheckBoxMenuItem();
@@ -1802,42 +1795,8 @@ public class GAlignFrame extends JInternalFrame
     };
     addMenuActionAndAccelerator(keyStroke, copyHighlighted, al);
     copyHighlighted.addActionListener(al);
-    
-    
 
-    ButtonGroup ssButtonGroup = new ButtonGroup();
-    final JRadioButtonMenuItem showAll = new JRadioButtonMenuItem(
-            MessageManager.getString("label.show_first"));
-    final JRadioButtonMenuItem showjPred = new JRadioButtonMenuItem(
-            MessageManager.getString("label.show_last"));
-    final JRadioButtonMenuItem show3DSS = new JRadioButtonMenuItem(
-            MessageManager.getString("label.show_last"));
-    ssButtonGroup.add(showAll);
-    ssButtonGroup.add(showjPred);
-    ssButtonGroup.add(show3DSS);
-    final boolean autoFirst1 = Cache
-            .getDefault(Preferences.SHOW_AUTOCALC_ABOVE, false);
-    showAll.setSelected(autoFirst1);
-    setShowAutoCalculatedAbove(autoFirst);
-    showAutoFirst.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        setShowAutoCalculatedAbove(showAutoFirst.isSelected());
-        sortAnnotations_actionPerformed();
-      }
-    });
-    showAutoLast.setSelected(!showAutoFirst.isSelected());
-    showAutoLast.addActionListener(new ActionListener()
-    {
-      @Override
-      public void actionPerformed(ActionEvent e)
-      {
-        setShowAutoCalculatedAbove(!showAutoLast.isSelected());
-        sortAnnotations_actionPerformed();
-      }
-    });
+    ButtonGroup ssButtonGroup = new ButtonGroup();   
 
     JMenu tooltipSettingsMenu = new JMenu(
             MessageManager.getString("label.sequence_id_tooltip"));
@@ -1847,12 +1806,47 @@ public class GAlignFrame extends JInternalFrame
     JMenu showSS = new JMenu(
             MessageManager.getString("label.show_secondary_structure")); 
     
-    showSS.addMouseListener(new MouseAdapter() {
+    JRadioButtonMenuItem radioButtonAllSS = new JRadioButtonMenuItem(MessageManager.getString("option.ss_providers_all"));
+    radioButtonAllSS.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+          showSS_actionPerformed(MessageManager.getString("option.ss_providers_all"));
+          // Select all checkboxes if "All" is selected
+          Component[] components = showSS.getMenuComponents();
+          for (Component component : components) {
+              if (component instanceof JCheckBoxMenuItem) {
+                  ((JCheckBoxMenuItem) component).setSelected(true);
+              }
+          }
+      }
+    });
+    ssButtonGroup.add(radioButtonAllSS);
+    showSS.add(radioButtonAllSS);
+    
+    JRadioButtonMenuItem radioButtonNoneSS = new JRadioButtonMenuItem(MessageManager.getString("option.ss_providers_none"));
+    radioButtonNoneSS.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+          showSS_actionPerformed(MessageManager.getString("option.ss_providers_none"));
+          // Remove selection of all checkboxes if "None" is selected
+          Component[] components = showSS.getMenuComponents();
+          for (Component component : components) {
+              if (component instanceof JCheckBoxMenuItem) {
+                  ((JCheckBoxMenuItem) component).setSelected(false);
+              }
+          }
+      }
+    });
+    ssButtonGroup.add(radioButtonNoneSS);
+    showSS.add(radioButtonNoneSS);
+    showSS.addSeparator();
+    
+    annotationsMenu.addMouseListener(new MouseAdapter() {
       
       @Override
       public void mouseEntered(MouseEvent e) {
 
-          updateShowSSRadioButtons(showSS, ssButtonGroup); // Update radio buttons every time the menu is clicked
+        updateShowSecondaryStructureMenu(showSS, ssButtonGroup); // Update radio buttons every time the menu is clicked
          
       }
     });
@@ -2599,10 +2593,6 @@ public class GAlignFrame extends JInternalFrame
 
   }
 
-  protected void jpred_actionPerformed(ActionEvent e)
-  {
-  }
-
   protected void scaleAbove_actionPerformed(ActionEvent e)
   {
   }
@@ -2873,13 +2863,14 @@ public class GAlignFrame extends JInternalFrame
     return null;
   }
 
-  protected void updateShowSSRadioButtons(JMenu showSS,
-          ButtonGroup ssButtonGroup)
+  protected void showSS_actionPerformed(String ssSourceSelection)
   {
     // TODO Auto-generated method stub
+    
   }
 
-  protected void showSS_actionPerformed(String ssSourceSelection)
+  protected void updateShowSecondaryStructureMenu(JMenu showSS,
+          ButtonGroup ssButtonGroup)
   {
     // TODO Auto-generated method stub
     
index 2f4052a..e620c1c 100644 (file)
@@ -5310,7 +5310,7 @@ public class Jalview2XML
     viewport.getResidueShading()
             .setConsensus(viewport.getSequenceConsensusHash());
     viewport.getResidueShading()
-    .setSsConsensus(viewport.getSequenceSSConsensusHash());
+    .setSSConsensusProfileMap(viewport.getSequenceSSConsensusHash());
     if (safeBoolean(view.isConservationSelected()) && cs != null)
     {
       viewport.getResidueShading()
index 4e9f669..2b73002 100644 (file)
@@ -33,6 +33,8 @@ import java.awt.geom.AffineTransform;
 import java.awt.image.ImageObserver;
 import java.util.BitSet;
 import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
 
 import org.jfree.graphics2d.svg.SVGGraphics2D;
 import org.jibble.epsgraphics.EpsGraphics2D;
@@ -91,7 +93,7 @@ public class AnnotationRenderer
 
   private ProfilesI hconsensus;
   
-  private ProfilesI hSSconsensus;
+  private Map<String, ProfilesI> hSSconsensus;
 
   private Hashtable<String, Object>[] complementConsensus;
 
@@ -432,16 +434,21 @@ public class AnnotationRenderer
       }
     }
     
-    else if(aa.autoCalculated && aa.label.startsWith(MessageManager.getString("label.ssconsensus_label"))) 
+    if(aa.autoCalculated && aa.label.startsWith(MessageManager.getString("label.ssconsensus_label"))) 
     {
-      return AAFrequency.extractProfile(
-              hSSconsensus.get(column),
-              av_ignoreGapsConsensus);
+      if(hSSconsensus!=null) {
+      for (String source : hSSconsensus.keySet()) {
+        if(aa.description.startsWith(source)) {
+      
+          return AAFrequency.extractProfile(
+                  hSSconsensus.get(source).get(column),
+                  av_ignoreGapsConsensus);
+        }
+      }
+      }
       
     }
     
-    else
-    {
       if (aa.autoCalculated && aa.label.startsWith("StrucConsensus"))
       {
         // TODO implement group structure consensus
@@ -463,7 +470,7 @@ public class AnnotationRenderer
                   av_ignoreGapsConsensus);
         }
       }
-    }
+    
     return null;
   }
 
@@ -529,7 +536,7 @@ public class AnnotationRenderer
             .getAlignmentStrucConsensusAnnotation();
     final AlignmentAnnotation complementConsensusAnnot = av
             .getComplementConsensusAnnotation();
-    final AlignmentAnnotation ssConsensusAnnot = av
+    final List<AlignmentAnnotation> ssConsensusAnnot = av
             .getAlignmentSecondaryStructureConsensusAnnotation();
 
     BitSet graphGroupDrawn = new BitSet();
@@ -557,7 +564,7 @@ public class AnnotationRenderer
         normaliseProfile = row.groupRef.isNormaliseSequenceLogo();
       }
       else if (row == consensusAnnot || row == structConsensusAnnot
-              || row == complementConsensusAnnot || row == ssConsensusAnnot)
+              || row == complementConsensusAnnot || (ssConsensusAnnot!=null && ssConsensusAnnot.contains(row)))
       {
         renderHistogram = av_renderHistogram;
         renderProfile = av_renderProfile;
@@ -1619,7 +1626,7 @@ public class AnnotationRenderer
               colour = profcolour.findColour(codonTranslation.charAt(0),
                       column, null);
             }
-            if(_aa.label == MessageManager.getString("label.ssconsensus_label")) {
+            if(_aa.label.startsWith(MessageManager.getString("label.ssconsensus_label"))) {
               colour = AlignmentUtils.getSecondaryStructureAnnotationColour(dc[0]);              
             }
             else
index b914c65..9231901 100644 (file)
@@ -63,20 +63,10 @@ public class ResidueShader implements ResidueShaderI
   private ProfilesI consensus;
   
   /*
-   * the consensus data for each column
+   * the ss consensus data for each column for each source
    */
-  private ProfilesI ssConsensus;
   
-
-  public ProfilesI getSsConsensus()
-  {
-    return ssConsensus;
-  }
-
-  public void setSsConsensus(ProfilesI ssConsensus)
-  {
-    this.ssConsensus = ssConsensus;
-  }
+  private Map<String, ProfilesI> ssConsensusProfileMap;
 
   /*
    * if true, apply shading of colour by conservation
@@ -144,7 +134,7 @@ public class ResidueShader implements ResidueShaderI
     this.conservationIncrement = rs.conservationIncrement;
     this.ignoreGaps = rs.ignoreGaps;
     this.pidThreshold = rs.pidThreshold;
-    this.ssConsensus = rs.ssConsensus;
+    this.ssConsensusProfileMap = rs.ssConsensusProfileMap;
   }
 
   /**
@@ -281,7 +271,7 @@ public class ResidueShader implements ResidueShaderI
   }
   
   @Override
-  public Color findSSColour(char symbol, int position, SequenceI seq)
+  public Color findSSColour(char symbol, int position, SequenceI seq, String source)
   {
     if (colourScheme == null)
     {
@@ -291,7 +281,7 @@ public class ResidueShader implements ResidueShaderI
     /*
      * get 'base' colour
      */
-    ProfileI profile = ssConsensus == null ? null : ssConsensus.get(position);
+    ProfileI profile = ssConsensusProfileMap.get(source) == null ? null : ssConsensusProfileMap.get(source).get(position);
     String modalSS = profile == null ? null
             : profile.getModalSS();
     float pid = profile == null ? 0f
@@ -463,4 +453,14 @@ public class ResidueShader implements ResidueShaderI
   {
     colourScheme = cs;
   }
+
+  public Map<String, ProfilesI> getSSConsensusProfileMap()
+  {
+    return ssConsensusProfileMap;
+  }
+
+  public void setSSConsensusProfileMap(Map<String, ProfilesI> ssConsensusProfileMap)
+  {
+    this.ssConsensusProfileMap = ssConsensusProfileMap;
+  }
 }
index 0412d21..42f4e2e 100644 (file)
@@ -35,7 +35,7 @@ public interface ResidueShaderI
 
   public abstract void setConsensus(ProfilesI cons);
   
-  public abstract void setSsConsensus(ProfilesI cons);
+  public abstract void setSSConsensusProfileMap(Map<String, ProfilesI> ssConsensusProfileMap);
 
   public abstract boolean conservationApplied();
 
@@ -84,6 +84,7 @@ public interface ResidueShaderI
 
   public abstract void setColourScheme(ColourSchemeI cs);
 
-  Color findSSColour(char symbol, int position, SequenceI seq);
+  Color findSSColour(char symbol, int position, SequenceI seq,
+          String source);
 
 }
\ No newline at end of file
index 6ad2f20..63bbe93 100644 (file)
@@ -25,6 +25,7 @@ import java.beans.PropertyChangeSupport;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.BitSet;
+import java.util.Collections;
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.Hashtable;
@@ -33,6 +34,7 @@ import java.util.List;
 import java.util.Map;
 
 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.analysis.AlignmentUtils;
 import jalview.analysis.Conservation;
 import jalview.analysis.TreeModel;
 import jalview.api.AlignCalcManagerI;
@@ -699,7 +701,9 @@ public abstract class AlignmentViewport
 
   protected AlignmentAnnotation consensus;
   
-  protected AlignmentAnnotation secondaryStructureConsensus;
+  protected List<AlignmentAnnotation> secondaryStructureConsensus;
+
+  protected List<String> secondaryStructureSources;
 
   protected AlignmentAnnotation complementConsensus;
 
@@ -722,7 +726,7 @@ public abstract class AlignmentViewport
    */
   protected ProfilesI hconsensus = null;
   
-  protected ProfilesI hSSConsensus = null;
+  protected Map<String, ProfilesI> hSSConsensusProfileMap = null;
   
   
 
@@ -744,6 +748,32 @@ public abstract class AlignmentViewport
   {
     hconservation = cons;
   }
+  
+  @Override
+  public List<String> getSecondaryStructureSources()
+  {
+    return secondaryStructureSources;
+  }
+
+  @Override
+  public void setSecondaryStructureSources(
+          List<String> secondaryStructureSources)
+  {
+    this.secondaryStructureSources = secondaryStructureSources;
+  }
+  
+  protected void setSecondaryStructureSources(AlignmentAnnotation[] aa)
+  {
+    List<String> sources = null;
+    
+    if(aa!=null) {
+      sources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(aa);
+      if(sources != null) {
+        sources.add(0,MessageManager.getString("option.ss_providers_all"));
+        setSecondaryStructureSources(sources);
+      }
+    }
+  }
 
   /**
    * percentage gaps allowed in a column before all amino acid properties should
@@ -764,11 +794,11 @@ public abstract class AlignmentViewport
   }
   
   @Override
-  public void setSequenceSSConsensusHash(ProfilesI hSSConsensus)
+  public void setSequenceSSConsensusHash(Map<String, ProfilesI> hSSConsensusProfileMap)
   {
-    this.hSSConsensus = hSSConsensus;
+    this.hSSConsensusProfileMap = hSSConsensusProfileMap;
   }
-  
+    
   @Override
   public void setComplementConsensusHash(
           Hashtable<String, Object>[] hconsensus)
@@ -781,12 +811,13 @@ public abstract class AlignmentViewport
   {
     return hconsensus;
   }
-  
+
   @Override
-  public ProfilesI getSequenceSSConsensusHash()
+  public Map<String, ProfilesI> getSequenceSSConsensusHash()
   {
-    return hSSConsensus;
+    return hSSConsensusProfileMap;
   }
+  
 
   @Override
   public Hashtable<String, Object>[] getComplementConsensusHash()
@@ -828,7 +859,7 @@ public abstract class AlignmentViewport
 
   
   @Override
-  public AlignmentAnnotation getAlignmentSecondaryStructureConsensusAnnotation()
+  public List<AlignmentAnnotation> getAlignmentSecondaryStructureConsensusAnnotation()
   {
     return secondaryStructureConsensus;
   }
@@ -930,7 +961,7 @@ public abstract class AlignmentViewport
   
 
   /**
-   * trigger update of consensus annotation
+   * trigger update of Secondary Structure consensus annotation
    */
   public void updateSecondaryStructureConsensus(final AlignmentViewPanel ap)
   {
@@ -939,11 +970,42 @@ public abstract class AlignmentViewport
     {
       return;
     }
+    if (secondaryStructureConsensus.size() != secondaryStructureSources.size()) {
+      
+      for(String source : secondaryStructureSources) {      
+        boolean ssConsensusForSourcePresent = false;
+        for(AlignmentAnnotation aa : secondaryStructureConsensus) {
+          if(aa.description.startsWith(source)) {
+            ssConsensusForSourcePresent = true;
+            break;
+          }
+        }
+        
+        if(!ssConsensusForSourcePresent) {
+          AlignmentAnnotation ssConsensus = new AlignmentAnnotation(MessageManager.getString("label.ssconsensus_label") + " "+source,
+                  source + MessageManager.getString("label.ssconsensus_descr"),
+                  new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+
+          ssConsensus.hasText = true;
+          ssConsensus.autoCalculated = true;
+          secondaryStructureConsensus.add(ssConsensus);
+          if (showSSConsensus)
+          {
+            ssConsensus.visible = true;
+            alignment.addAnnotation(ssConsensus);
+            
+          }
+        }
+      }
+    }
     if (calculator
             .getRegisteredWorkersOfClass(SecondaryStructureConsensusThread.class) == null)
     {
       calculator.registerWorker(new SecondaryStructureConsensusThread(this, ap));
     }
+    ap.adjustAnnotationHeight();
+
+    
   }
 
   // --------START Structure Conservation
@@ -2042,10 +2104,21 @@ 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);
+      setSecondaryStructureSources(alignment.getAlignmentAnnotation());
+      List<String> secondaryStructureSources = getSecondaryStructureSources();
+
+      if(secondaryStructureSources!=null) {
+
+        secondaryStructureConsensus = new ArrayList<AlignmentAnnotation>();
+        for (String ssSource : secondaryStructureSources) {
+        
+          AlignmentAnnotation ssConsensus = new AlignmentAnnotation(MessageManager.getString("label.ssconsensus_label") + " "+ssSource,
+                  ssSource + MessageManager.getString("label.ssconsensus_descr"),
+                  new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+          secondaryStructureConsensus.add(ssConsensus);
+        }
+        
+      }
       
       initConsensus(consensus);
       initSSConsensus(secondaryStructureConsensus);
@@ -2106,14 +2179,20 @@ public abstract class AlignmentViewport
     }
   }
   
-  private void initSSConsensus(AlignmentAnnotation aa)
+  private void initSSConsensus(List<AlignmentAnnotation> secondaryStructureConsensuses)
   {
-    aa.hasText = true;
-    aa.autoCalculated = true;
-
-    if (showSSConsensus)
-    {
-      alignment.addAnnotation(aa);
+    if(secondaryStructureConsensuses == null) {
+      return;
+    }
+    for(AlignmentAnnotation aa : secondaryStructureConsensuses) {
+      aa.hasText = true;
+      aa.autoCalculated = true;
+  
+      if (showSSConsensus)
+      {
+        alignment.addAnnotation(aa);
+      }
+      
     }
   }
 
@@ -2317,7 +2396,16 @@ public abstract class AlignmentViewport
         {
           updateCalcs = true;
           alignment.addAnnotation(sg.getConsensus(), 0);
-          alignment.addAnnotation(sg.getSSConsensus(), 0);
+          
+          List<String> secondaryStructureSources = getSecondaryStructureSources();
+          if(secondaryStructureSources !=null) {
+            List<AlignmentAnnotation> ssAa = sg.getSSConsensus(secondaryStructureSources);
+            if(ssAa != null) {
+              for(AlignmentAnnotation aa : ssAa) {
+                alignment.addAnnotation(aa, 0);
+              }
+            }
+          }
         }
         // refresh the annotation rows
         if (updateCalcs)
@@ -3108,6 +3196,7 @@ public abstract class AlignmentViewport
     return sq;
   }
   
+  //to do jal-4386
   public SequenceI getSSConsensusSeq()
   {
     if (secondaryStructureConsensus == null)
@@ -3119,23 +3208,23 @@ public abstract class AlignmentViewport
       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);
-        }
-      }
-    }
+//    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 "
index 04cefe5..282b337 100644 (file)
  */
 package jalview.workers;
 
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import jalview.analysis.AAFrequency;
+import jalview.analysis.AlignmentUtils;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.datamodel.AlignmentAnnotation;
@@ -29,6 +35,7 @@ import jalview.datamodel.Annotation;
 import jalview.datamodel.ProfilesI;
 import jalview.datamodel.SequenceI;
 import jalview.renderer.ResidueShaderI;
+import jalview.util.MessageManager;
 
 public class SecondaryStructureConsensusThread extends AlignCalcWorker
 {
@@ -49,7 +56,7 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
     // long started = System.currentTimeMillis();
     try
     {
-      AlignmentAnnotation ssConsensus = getSSConsensusAnnotation();
+      List<AlignmentAnnotation> ssConsensus = getSSConsensusAnnotation();
       AlignmentAnnotation gap = getGapAnnotation();
       if ((ssConsensus == null && gap == null) || calcMan.isPending(this))
       {
@@ -84,7 +91,8 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
         calcMan.workerComplete(this);
         return;
       }
-
+      
+      setSecondaryStructureSources();
       eraseSSConsensus(aWidth);
       computeSSConsensus(alignment);
       updateResultAnnotation(true);
@@ -115,10 +123,12 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
    */
   protected void eraseSSConsensus(int aWidth)
   {
-    AlignmentAnnotation ssConsensus = getSSConsensusAnnotation();
-    if (ssConsensus != null)
-    {
-      ssConsensus.annotations = new Annotation[aWidth];
+    List<AlignmentAnnotation> ssConsensuses = getSSConsensusAnnotation();
+    for(AlignmentAnnotation ssConsensus : ssConsensuses) {
+      if (ssConsensus != null)
+      {
+        ssConsensus.annotations = new Annotation[aWidth];
+      }
     }
     AlignmentAnnotation gap = getGapAnnotation();
     if (gap != null)
@@ -135,11 +145,17 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
 
     SequenceI[] aseqs = getSequences();
     int width = alignment.getWidth();
-    ProfilesI hSSConsensus = AAFrequency.calculateSS(aseqs, width, 0, width,
-            true);
+    Map<String, ProfilesI> hSSConsensusProfileMap = new HashMap<String, ProfilesI>();
+    List <String> ssSources = getSecondaryStructureSources();
+    for(String ssSource : ssSources) {
+      ProfilesI hSSConsensus = AAFrequency.calculateSS(aseqs, width, 0, width,
+              true, ssSource);
+      hSSConsensusProfileMap.put(ssSource, hSSConsensus);
+    }
+    
 
-    alignViewport.setSequenceSSConsensusHash(hSSConsensus);
-    setColourSchemeConsensus(hSSConsensus);
+    alignViewport.setSequenceSSConsensusHash(hSSConsensusProfileMap);
+    setColourSchemeConsensus(hSSConsensusProfileMap);
   }
 
   /**
@@ -153,12 +169,12 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
   /**
    * @param hconsensus
    */
-  protected void setColourSchemeConsensus(ProfilesI hSSconsensus)
+  protected void setColourSchemeConsensus(Map<String, ProfilesI> ssConsensusProfileMap)
   {
     ResidueShaderI cs = alignViewport.getResidueShading();
     if (cs != null)
     {
-      cs.setSsConsensus(hSSconsensus);
+      cs.setSSConsensusProfileMap(ssConsensusProfileMap);
     }
   }
 
@@ -167,10 +183,33 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
    * 
    * @return
    */
-  protected AlignmentAnnotation getSSConsensusAnnotation()
+  protected List<AlignmentAnnotation> getSSConsensusAnnotation()
   {
     return alignViewport.getAlignmentSecondaryStructureConsensusAnnotation();
   }
+  
+  /**
+   * Get the Consensus annotation for the alignment
+   * 
+   * @return
+   */
+  protected void setSecondaryStructureSources()
+  {
+    List<String> sources = null;
+    AlignmentAnnotation[] aa = alignViewport.getAlignment().getAlignmentAnnotation();
+    if(aa!=null) {
+      sources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(aa);
+      if(sources != null) {
+        sources.add(0, MessageManager.getString("option.ss_providers_all"));
+        alignViewport.setSecondaryStructureSources(sources);
+      }
+    }
+  }
+  
+  protected List<String> getSecondaryStructureSources()
+  {
+    return alignViewport.getSecondaryStructureSources();
+  }
 
   /**
    * Get the Gap annotation for the alignment
@@ -194,18 +233,30 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
 
   public void updateResultAnnotation(boolean immediate)
   {
-    AlignmentAnnotation ssConsensus = getSSConsensusAnnotation();
-    ProfilesI hSSConsensus = (ProfilesI) getViewportSSConsensus();
+    List<AlignmentAnnotation> ssConsensuses = getSSConsensusAnnotation();
+    Map<String, ProfilesI> ssConsensusProfileMap = getViewportSSConsensus();
+    for(AlignmentAnnotation ssConsensus : ssConsensuses) {
+      ProfilesI ssConsensusProfile = null;
+      for(String source: ssConsensusProfileMap.keySet()) {
+        if(ssConsensus.description.startsWith(source)) {
+          ssConsensusProfile = ssConsensusProfileMap.get(source);
+          break;
+        }
+      }
+    if(ssConsensusProfile==null) {
+      continue;
+    }
     if (immediate || !calcMan.isWorking(this) && ssConsensus != null
-            && hSSConsensus != null)
+            && ssConsensusProfile != null)
     {
-      deriveSSConsensus(ssConsensus, hSSConsensus);
+      deriveSSConsensus(ssConsensus, ssConsensusProfile);
       AlignmentAnnotation gap = getGapAnnotation();
       if (gap != null)
       {
-        deriveGap(gap, hSSConsensus);
+        deriveGap(gap, ssConsensusProfile);
       }
     }
+    }
   }
 
   /**
@@ -217,12 +268,12 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
    * @param hconsensus
    *          the computed consensus data
    */
-  protected void deriveSSConsensus(AlignmentAnnotation ssConsensusAnnotation,
+  protected void deriveSSConsensus(AlignmentAnnotation ssConsensus,
           ProfilesI hSSConsensus)
   {
 
     long nseq = getSequences().length;
-    AAFrequency.completeSSConsensus(ssConsensusAnnotation, hSSConsensus,
+    AAFrequency.completeSSConsensus(ssConsensus, hSSConsensus,
             hSSConsensus.getStartColumn(), hSSConsensus.getEndColumn() + 1,
             alignViewport.isIgnoreGapsConsensus(),
             alignViewport.isShowSequenceLogo(), nseq);
@@ -250,7 +301,7 @@ public class SecondaryStructureConsensusThread extends AlignCalcWorker
    * 
    * @return
    */
-  protected Object getViewportSSConsensus()
+  protected Map<String, ProfilesI> getViewportSSConsensus()
   {
     // TODO convert ComplementConsensusThread to use Profile
     return alignViewport.getSequenceSSConsensusHash();