JAL-4411 store class of provider in PDBEntry
[jalview.git] / src / jalview / analysis / AlignmentUtils.java
index 403991a..d88950c 100644 (file)
@@ -37,6 +37,7 @@ import java.util.Set;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import jalview.api.AlignCalcWorkerI;
 import jalview.bin.Console;
 import jalview.commands.RemoveGapColCommand;
 import jalview.datamodel.AlignedCodon;
@@ -55,6 +56,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.datamodel.features.SequenceFeatures;
+import jalview.gui.AlignmentPanel;
 import jalview.io.gff.SequenceOntologyI;
 import jalview.schemes.ResidueProperties;
 import jalview.util.Comparison;
@@ -62,6 +64,7 @@ import jalview.util.DBRefUtils;
 import jalview.util.IntRangeComparator;
 import jalview.util.MapList;
 import jalview.util.MappingUtils;
+import jalview.workers.SecondaryStructureConsensusThread;
 
 /**
  * grab bag of useful alignment manipulation operations Expect these to be
@@ -76,6 +79,17 @@ public class AlignmentUtils
 
   private static final String SEQUENCE_VARIANT = "sequence_variant:";
 
+  
+  private static final Map<String, String> SECONDARY_STRUCTURE_LABELS = new HashMap<>();
+
+  static {
+      SECONDARY_STRUCTURE_LABELS.put("Secondary Structure", "3D Structures");
+      SECONDARY_STRUCTURE_LABELS.put("jnetpred", "JPred");
+      // Add other secondary structure labels here if needed
+  }
+  
+  private static final String SS_ANNOTATION_LABEL = "Secondary Structure";
+
   /*
    * the 'id' attribute is provided for variant features fetched from
    * Ensembl using its REST service with JSON format 
@@ -184,10 +198,10 @@ public class AlignmentUtils
       // TODO use Character.toLowerCase to avoid creating String objects?
       char[] upstream = new String(ds
               .getSequence(s.getStart() - 1 - ustream_ds, s.getStart() - 1))
-              .toLowerCase(Locale.ROOT).toCharArray();
+                      .toLowerCase(Locale.ROOT).toCharArray();
       char[] downstream = new String(
               ds.getSequence(s_end - 1, s_end + dstream_ds))
-              .toLowerCase(Locale.ROOT).toCharArray();
+                      .toLowerCase(Locale.ROOT).toCharArray();
       char[] coreseq = s.getSequence();
       char[] nseq = new char[offset + upstream.length + downstream.length
               + coreseq.length];
@@ -547,7 +561,8 @@ public class AlignmentUtils
       if (translated == null || !(aaRes == translated.charAt(0)))
       {
         // debug
-        // System.out.println(("Mismatch at " + i + "/" + aaResidue + ": "
+        // jalview.bin.Console.outPrintln(("Mismatch at " + i + "/" + aaResidue
+        // + ": "
         // + codon + "(" + translated + ") != " + aaRes));
         return false;
       }
@@ -698,7 +713,8 @@ public class AlignmentUtils
          * unmapped position; treat like a gap
          */
         sourceGapMappedLength += ratio;
-        // System.err.println("Can't align: no codon mapping to residue "
+        // jalview.bin.Console.errPrintln("Can't align: no codon mapping to
+        // residue "
         // + sourceDsPos + "(" + sourceChar + ")");
         // return;
         continue;
@@ -883,7 +899,8 @@ public class AlignmentUtils
   {
     if (protein.isNucleotide() || !dna.isNucleotide())
     {
-      System.err.println("Wrong alignment type in alignProteinAsDna");
+      jalview.bin.Console
+              .errPrintln("Wrong alignment type in alignProteinAsDna");
       return 0;
     }
     List<SequenceI> unmappedProtein = new ArrayList<>();
@@ -908,7 +925,8 @@ public class AlignmentUtils
   {
     if (protein.isNucleotide() || !dna.isNucleotide())
     {
-      System.err.println("Wrong alignment type in alignProteinAsDna");
+      jalview.bin.Console
+              .errPrintln("Wrong alignment type in alignProteinAsDna");
       return 0;
     }
     // todo: implement this
@@ -988,7 +1006,7 @@ public class AlignmentUtils
                           .getLength() == mappedFromLength - 1);
           if (cdsLength != mappedToLength && !addStopCodon)
           {
-            System.err.println(String.format(
+            jalview.bin.Console.errPrintln(String.format(
                     "Can't align cds as protein (length mismatch %d/%d): %s",
                     cdsLength, mappedToLength, cdsSeq.getName()));
           }
@@ -1162,7 +1180,7 @@ public class AlignmentUtils
         AlignedCodon codon = sequenceCodon.getValue();
         if (codon.peptideCol > 1)
         {
-          System.err.println(
+          jalview.bin.Console.errPrintln(
                   "Problem mapping protein with >1 unmapped start positions: "
                           + seq.getName());
         }
@@ -1471,19 +1489,20 @@ public class AlignmentUtils
          */
         final Iterable<AlignmentAnnotation> matchedAlignmentAnnotations = al
                 .findAnnotations(seq, dsann.getCalcId(), dsann.label);
-        boolean found=false;
+        boolean found = false;
         if (matchedAlignmentAnnotations != null)
         {
-          for (AlignmentAnnotation matched:matchedAlignmentAnnotations)
+          for (AlignmentAnnotation matched : matchedAlignmentAnnotations)
           {
             if (dsann.description.equals(matched.description))
             {
-              found=true;
+              found = true;
               break;
             }
           }
         }
-        if (!found) {
+        if (!found)
+        {
           result.add(dsann);
           if (labelForCalcId != null)
           {
@@ -1503,14 +1522,17 @@ public class AlignmentUtils
 
   /**
    * Adds annotations to the top of the alignment annotations, in the same order
-   * as their related sequences. If you already have an annotation and want to add it to a sequence in an alignment use {@code addReferenceAnnotationTo}
+   * as their related sequences. If you already have an annotation and want to
+   * add it to a sequence in an alignment use {@code addReferenceAnnotationTo}
    * 
    * @param annotations
    *          the annotations to add
    * @param alignment
    *          the alignment to add them to
    * @param selectionGroup
-   *          current selection group (or null if none)
+   *          current selection group - may be null, if provided then any added
+   *          annotation will be trimmed to just those columns in the selection
+   *          group
    */
   public static void addReferenceAnnotations(
           Map<SequenceI, List<AlignmentAnnotation>> annotations,
@@ -1520,51 +1542,77 @@ public class AlignmentUtils
     {
       for (AlignmentAnnotation ann : annotations.get(seq))
       {
-        addReferenceAnnotationTo(alignment, seq,ann,selectionGroup);
+        addReferenceAnnotationTo(alignment, seq, ann, selectionGroup);
       }
     }
   }
+  
+  
+  public static boolean isSSAnnotationPresent( Map<SequenceI, List<AlignmentAnnotation>> annotations) {
+    
+    for (SequenceI seq : annotations.keySet())
+    {
+      for (AlignmentAnnotation ann : annotations.get(seq))
+      {
+        if(ann.getDescription(false).startsWith(SS_ANNOTATION_LABEL)) {                    
+          return true;
+        }       
+      }
+    }
+    return false;
+  }
+
   /**
-   * Make a copy of a reference annotation {@code ann} and add it to an alignment sequence {@code seq} in {@code alignment}, optionally limited to the extent of {@code selectionGroup}
+   * Make a copy of a reference annotation {@code ann} and add it to an
+   * alignment sequence {@code seq} in {@code alignment}, optionally limited to
+   * the extent of {@code selectionGroup}
+   * 
    * @param alignment
    * @param seq
    * @param ann
-   * @param selectionGroup - may be null
+   * @param selectionGroup
+   *          current selection group - may be null, if provided then any added
+   *          annotation will be trimmed to just those columns in the selection
+   *          group
    * @return annotation added to {@code seq and {@code alignment}
    */
-  public static AlignmentAnnotation addReferenceAnnotationTo(final AlignmentI alignment, final SequenceI seq,final AlignmentAnnotation ann,final SequenceGroup selectionGroup)
+  public static AlignmentAnnotation addReferenceAnnotationTo(
+          final AlignmentI alignment, final SequenceI seq,
+          final AlignmentAnnotation ann, final SequenceGroup selectionGroup)
   {
-        AlignmentAnnotation copyAnn = new AlignmentAnnotation(ann);
-        int startRes = 0;
-        int endRes = ann.annotations.length;
-        if (selectionGroup != null)
-        {
-          startRes = selectionGroup.getStartRes();
-          endRes = selectionGroup.getEndRes();
-        }
-        copyAnn.restrict(startRes, endRes + 0);
+    AlignmentAnnotation copyAnn = new AlignmentAnnotation(ann);
+    int startRes = 0;
+    int endRes = ann.annotations.length;
+    if (selectionGroup != null)
+    {
+      startRes = -1 + Math.min(seq.getEnd(), Math.max(seq.getStart(),
+              seq.findPosition(selectionGroup.getStartRes())));
+      endRes = -1 + Math.min(seq.getEnd(),
+              seq.findPosition(selectionGroup.getEndRes()));
 
-        /*
-         * Add to the sequence (sets copyAnn.datasetSequence), unless the
-         * original annotation is already on the sequence.
-         */
-        if (!seq.hasAnnotation(ann))
-        {
-          ContactMatrixI cm = seq.getDatasetSequence()
-                  .getContactMatrixFor(ann);
-          if (cm != null)
-          {
-            seq.addContactListFor(copyAnn, cm);
-          }
-          seq.addAlignmentAnnotation(copyAnn);
-        }
-        // adjust for gaps
-        copyAnn.adjustForAlignment();
-        // add to the alignment and set visible
-        alignment.addAnnotation(copyAnn);
-        copyAnn.visible = true;
-      
-        return copyAnn;
+    }
+    copyAnn.restrict(startRes, endRes + 0);
+
+    /*
+     * Add to the sequence (sets copyAnn.datasetSequence), unless the
+     * original annotation is already on the sequence.
+     */
+    if (!seq.hasAnnotation(ann))
+    {
+      ContactMatrixI cm = seq.getDatasetSequence().getContactMatrixFor(ann);
+      if (cm != null)
+      {
+        seq.addContactListFor(copyAnn, cm);
+      }
+      seq.addAlignmentAnnotation(copyAnn);
+    }
+    // adjust for gaps
+    copyAnn.adjustForAlignment();
+    // add to the alignment and set visible
+    alignment.addAnnotation(copyAnn);
+    copyAnn.visible = true;
+
+    return copyAnn;
   }
 
   /**
@@ -2759,8 +2807,8 @@ public class AlignmentUtils
                 fromRange[i + 1]);
         if (range == null)
         {
-          System.err.println("Error in mapping " + seqMap + " from "
-                  + fromSeq.getName());
+          jalview.bin.Console.errPrintln("Error in mapping " + seqMap
+                  + " from " + fromSeq.getName());
           return false;
         }
         int fromCol = fromSeq.findIndex(fromRange[i]);
@@ -2811,4 +2859,41 @@ public class AlignmentUtils
     }
     return true;
   }
+  
+
+  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 (SECONDARY_STRUCTURE_LABELS.containsKey(label) && !addedLabels.contains(label)) {
+              ssSources.add(SECONDARY_STRUCTURE_LABELS.get(label));
+              addedLabels.add(label); // Add the label to the set
+          }
+      }
+
+      return ssSources;
+  }
+  
+  public static boolean isSecondaryStructurePresent(AlignmentAnnotation[] annotations)
+  {
+    boolean ssPresent = false;
+    
+    for (AlignmentAnnotation aa : annotations)
+    {
+      if(ssPresent) {
+        break;
+      }     
+
+      if (SECONDARY_STRUCTURE_LABELS.containsKey(aa.label)) {
+          ssPresent = true;
+          break;
+      }
+    }
+    
+    return ssPresent;
+    
+  }
 }