Merge branch 'develop' into spike/JAL-4047/JAL-4048_columns_in_sequenceID
[jalview.git] / src / jalview / analysis / AlignmentUtils.java
index 0906872..f470dc6 100644 (file)
@@ -184,10 +184,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 +547,7 @@ 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 +698,7 @@ 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 +883,7 @@ 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 +908,7 @@ 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 +988,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 +1162,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 +1471,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 +1504,15 @@ public class AlignmentUtils
 
   /**
    * Adds annotations to the top of the alignment annotations, in the same order
-   * as their related sequences.
+   * 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,38 +1522,60 @@ public class AlignmentUtils
     {
       for (AlignmentAnnotation ann : annotations.get(seq))
       {
-        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);
+        addReferenceAnnotationTo(alignment, seq, ann, selectionGroup);
+      }
+    }
+  }
 
-        /*
-         * 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;
+  /**
+   * 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
+   *          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)
+  {
+    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()));
+
+    }
+    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;
   }
 
   /**
@@ -2746,7 +2770,7 @@ public class AlignmentUtils
                 fromRange[i + 1]);
         if (range == null)
         {
-          System.err.println("Error in mapping " + seqMap + " from "
+          jalview.bin.Console.errPrintln("Error in mapping " + seqMap + " from "
                   + fromSeq.getName());
           return false;
         }