implement new insert annotation row method and ensure group annotation rows are remov...
[jalview.git] / src / jalview / datamodel / Alignment.java
index c74be73..afe7032 100755 (executable)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
- * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer (Development Version 2.4.1)
+ * Copyright (C) 2009 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
  * 
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -25,6 +25,10 @@ import jalview.analysis.*;
 /**
  * Data structure to hold and manipulate a multiple sequence alignment
  */
+/**
+ * @author JimP
+ *
+ */
 public class Alignment implements AlignmentI
 {
   protected Alignment dataset;
@@ -352,6 +356,14 @@ public class Alignment implements AlignmentI
   {
     if (groups.contains(g))
     {
+      if (annotations!=null && annotations.length>0)
+      {
+        if (g.hasAnnotationRows())
+        {  // remove any annotation references. 
+          deleteAnnotation(g.getConsensus());// todo - create=false flag so we don't create another object unnecessarily
+          deleteAnnotation(g.getConservationRow());
+        }
+      }
       groups.removeElement(g);
     }
   }
@@ -606,14 +618,19 @@ public class Alignment implements AlignmentI
     return swap;
   }
 
-  /**
-   * DOCUMENT ME!
-   * 
-   * @param aa
-   *                DOCUMENT ME!
+  /* (non-Javadoc)
+   * @see jalview.datamodel.AlignmentI#addAnnotation(jalview.datamodel.AlignmentAnnotation)
    */
   public void addAnnotation(AlignmentAnnotation aa)
   {
+    addAnnotation(aa, -1);
+  }
+  
+  /* (non-Javadoc)
+   * @see jalview.datamodel.AlignmentI#addAnnotation(jalview.datamodel.AlignmentAnnotation, int)
+   */
+  public void addAnnotation(AlignmentAnnotation aa, int pos)
+  {
     int aSize = 1;
     if (annotations != null)
     {
@@ -621,16 +638,24 @@ public class Alignment implements AlignmentI
     }
 
     AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
-
-    temp[aSize - 1] = aa;
-
     int i = 0;
-
+    if (pos==-1 || pos>=aSize) {
+      temp[aSize - 1] = aa;
+    } else {
+      temp[pos] = aa;
+    }
     if (aSize > 1)
     {
-      for (i = 0; i < (aSize - 1); i++)
+      int p=0;
+      for (i = 0; i < (aSize-1); i++,p++)
       {
-        temp[i] = annotations[i];
+        if (p==pos)
+        {
+          p++;
+        }
+        if (p<temp.length) {
+          temp[p] = annotations[i];
+        }
       }
     }
 
@@ -794,6 +819,98 @@ public class Alignment implements AlignmentI
     }
     return modified;
   }
+  /**
+   * Justify the sequences to the left or right by deleting and inserting gaps before the initial residue or after the terminal residue
+   * @param right true if alignment padded to right, false to justify to left
+   * @return true if alignment was changed
+   */
+  public boolean justify(boolean right)
+  {
+    boolean modified = false;
+
+    // Remove excess gaps from the end of alignment
+    int maxLength = -1;
+    int ends[] = new int[sequences.size()*2];
+    SequenceI current;
+    for (int i = 0; i < sequences.size(); i++)
+    {
+      current = getSequenceAt(i);
+      // This should really be a sequence method
+      ends[i*2] = current.findIndex(current.getStart());
+      ends[i*2+1] = current.findIndex(current.getStart()+current.getLength());
+      boolean hitres=false;
+      for (int j = 0,rs=0,ssiz=current.getLength(); j<ssiz; j++)
+      {
+        if (!jalview.util.Comparison.isGap(current.getCharAt(j)))
+        {
+          if (!hitres)
+          {
+            ends[i*2] = j;
+            hitres=true;
+          } else {
+            ends[i*2+1] = j;
+            if (j-ends[i*2]>maxLength)
+            {
+              maxLength = j-ends[i*2];
+            }
+          }
+        }
+      }
+    }
+
+    maxLength++;
+    // now edit the flanking gaps to justify to either left or right
+    int cLength,extent,diff;
+    for (int i = 0; i < sequences.size(); i++)
+    {
+      current = getSequenceAt(i);
+      
+      cLength = 1+ends[i*2+1]-ends[i*2];
+      diff = maxLength-cLength; // number of gaps to indent
+      extent = current.getLength();
+      if (right)
+      {
+        // right justify
+        if (extent>ends[i*2+1])
+        {
+          current.deleteChars(ends[i*2+1]+1, extent);
+          modified = true;
+        }
+        if (ends[i*2]>diff)
+        {
+          current.deleteChars(0, ends[i*2]-diff);
+          modified = true;
+        } else {
+          if (ends[i*2]<diff)
+          {
+            current.insertCharAt(0, diff-ends[i*2],gapCharacter);
+            modified = true;
+          }
+        }
+      } else {
+        // left justify
+        if (ends[i*2]>0)
+        {
+          current.deleteChars(0, ends[i*2]);
+          modified = true;
+          ends[i*2+1]-=ends[i*2];
+          extent-=ends[i*2];
+        }
+        if (extent>maxLength)
+        {
+          current.deleteChars(maxLength+1, extent);
+          modified = true;
+        } else {
+          if (extent<maxLength)
+          {
+            current.insertCharAt(extent, maxLength-extent,gapCharacter);
+            modified = true;
+          }
+        }
+      }
+    }
+    return modified;
+  }
 
   public HiddenSequences getHiddenSequences()
   {