JAL-4386 PCA/Tree Calculation for Secondary Structures: Changes related to dropdown...
[jalview.git] / src / jalview / analysis / scoremodels / SecondaryStructureDistanceModel.java
index 635132e..3a719d8 100644 (file)
@@ -32,7 +32,9 @@ import jalview.math.Matrix;
 import jalview.math.MatrixI;
 import jalview.util.SetUtils;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 /* This class contains methods to calculate distance score between 
@@ -44,6 +46,8 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
   private static final String NAME = "Secondary Structure Similarity";
   
   private static final String SS_ANNOTATION_LABEL = "Secondary Structure";
+  
+  private static final String SS_ANNOTATION_FROM_JPRED_LABEL = "jnetpred";
 
   private String description;
   
@@ -127,7 +131,8 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
   @Override
   public MatrixI findDistances(AlignmentView seqData,
           SimilarityParamsI params)
-  {
+  {   
+    
     SeqCigar[] seqs = seqData.getSequences();
     int noseqs = seqs.length; //no of sequences
     int cpwidth = 0; // = seqData.getWidth();
@@ -135,8 +140,21 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
       
     // need to get real position for view position
     int[] viscont = seqData.getVisibleContigs();
+    Map<String, HashSet<String>> calcIdMapInAlignmentAnnotation = new HashMap<String,HashSet<String>>();
+    
+    AlignmentAnnotation[] alignAnnotList = fr.getViewport().getAlignment().getAlignmentAnnotation();
+    if(alignAnnotList.length > 0) {
+      
+      for (AlignmentAnnotation aa: alignAnnotList) {
+        if (SS_ANNOTATION_LABEL.equals(aa.label) || SS_ANNOTATION_FROM_JPRED_LABEL.equals(aa.label)) {
+            calcIdMapInAlignmentAnnotation.computeIfAbsent(aa.getCalcId(), k -> new HashSet<>()).add(aa.description);
+        }
+        
+      }      
+    }
+    
     
-    Set<SeqCigar> seqsWithUndefinedSS = findSeqsWithUndefinedSS(seqs);
+    Set<SeqCigar> seqsWithUndefinedSS = findSeqsWithUndefinedSS(seqs, calcIdMapInAlignmentAnnotation);
 
 
     /*
@@ -168,6 +186,7 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
           {
             SeqCigar sc1 = seqs[i];
             SeqCigar sc2 = seqs[j];
+                         
 
             //check if ss is defined
             boolean undefinedSS1 = seqsWithUndefinedSS.contains(sc1);
@@ -207,8 +226,8 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
 
             /*
              * gap-gap always scores zero
-             * residue-residue is always scored
-             * include gap-residue score if params say to do so
+             * ss-ss is always scored
+             * include gap-ss scores 1 if params say to do so
              */
             if ((!gap1 && !gap2) || params.includeGaps())
             {
@@ -273,25 +292,39 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
    *          (0..)
    * @return
    */
-  protected Set<SeqCigar> findSeqsWithUndefinedSS(
-          SeqCigar[] seqs)
-  {
-    Set<SeqCigar> seqsWithUndefinedSS = new HashSet<>();
-    for (SeqCigar seq : seqs)
-    {
-      
-      AlignmentAnnotation[] aa = seq.getRefSeq().getAnnotation(SS_ANNOTATION_LABEL);
-      if (aa == null) {
-         /*
-         * secondary structure is undefined for the seq
-         * Add seq in the set
-         */        
-        seqsWithUndefinedSS.add(seq);
+  private static final String[] SS_ANNOTATION_LABELS = {
+      SS_ANNOTATION_LABEL, 
+      SS_ANNOTATION_FROM_JPRED_LABEL 
+  };
+
+  protected Set<SeqCigar> findSeqsWithUndefinedSS(SeqCigar[] seqs, Map<String, HashSet<String>> calcIdMapInAlignmentAnnotation) {
+      Set<SeqCigar> seqsWithUndefinedSS = new HashSet<>();
+      for (SeqCigar seq : seqs) {
+          if (isSSUndefinedOrNotAdded(seq, calcIdMapInAlignmentAnnotation)) {
+              seqsWithUndefinedSS.add(seq);
+          }
       }
-    }
-    return seqsWithUndefinedSS;
+      return seqsWithUndefinedSS;
+  }
+
+  private boolean isSSUndefinedOrNotAdded(SeqCigar seq, Map<String, HashSet<String>> calcIdMapInAlignmentAnnotation) {
+      for (String label : SS_ANNOTATION_LABELS) {
+          AlignmentAnnotation[] annotations = seq.getRefSeq().getAnnotation(label);
+          if (annotations != null) {
+              for (AlignmentAnnotation annotation : annotations) {                
+                HashSet<String> descriptionList = calcIdMapInAlignmentAnnotation.get(annotation.getCalcId());
+                  if (descriptionList.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;
   }
   
+  
   /**
    * Finds secondary structure annotation for a given sequence (SeqCigar) 
    * and column position corresponding to the sequence.
@@ -310,15 +343,21 @@ public class SecondaryStructureDistanceModel extends DistanceScoreModel
          
          //fetch the position in sequence for the column and finds the
          //corresponding secondary structure annotation
+         //TO DO - consider based on priority
          int seqPosition = seq.findPosition(columnPosition);
          AlignmentAnnotation[] aa = seq.getRefSeq().getAnnotation(SS_ANNOTATION_LABEL);
+         
+         if(aa == null) {
+           aa = seq.getRefSeq().getAnnotation(SS_ANNOTATION_FROM_JPRED_LABEL);
+         }
+         
          if (aa != null) {
            if (aa[0].getAnnotationForPosition(seqPosition) != null) {
              Annotation a = aa[0].getAnnotationForPosition(seqPosition);
              ss = a.secondaryStructure;
              
              //There is no representation for coil and it can be either ' ' or null. 
-             if (ss == ' ') {
+             if (ss == ' ' || ss == '-') {
                ss = COIL; 
              }
            }