added copy consensus sequence to consensus annotation popup menu
[jalview.git] / src / jalview / datamodel / ColumnSelection.java
index 6b9f28d..2d22231 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Jalview - A Sequence Alignment Editor and Viewer
- * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+ * Copyright (C) 2006 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
@@ -173,7 +173,7 @@ public class ColumnSelection
      * propagate shift in alignment columns to column selection
      *
      * @param start beginning of edit
-     * @param change shift in edit (-ve or +ve number of columns)
+     * @param left shift in edit (+ve for removal, or -ve for inserts)
      */
     public void compensateForEdit(int start, int change)
     {
@@ -204,13 +204,63 @@ public class ColumnSelection
           }
         }
     }
+    /**
+     * propagate shift in alignment columns to column selection
+     * special version of compensateForEdit - allowing for edits within hidden regions
+     * @param start beginning of edit
+     * @param left shift in edit (+ve for removal, or -ve for inserts)
+     */
+    private void compensateForDelEdits(int start, int change)
+    {
+        for (int i = 0; i < size(); i++)
+        {
+            int temp = columnAt(i);
+
+            if (temp >= start)
+            {
+                selected.setElementAt(new Integer(temp - change), i);
+            }
+        }
+
+        if(hiddenColumns!=null)
+        {
+          for(int i=0; i<hiddenColumns.size(); i++)
+          {
+            int[] region = (int[]) hiddenColumns.elementAt(i);
+            if(region[0] >= start)
+            {
+              region[0] -= change;
+            }
+            if (region[1]>= start) {
+              region[1] -=change;
+            }
+            if (region[1]<region[0]) {
+              hiddenColumns.removeElementAt(i--);
+            }
+
+            if(region[0]<0)
+              region[0] = 0;
+            if(region[1] <0)
+             region[1] = 0;
+          }
+        }
+    }
+    /**
+     * Adjust hidden column boundaries based on a series of column
+     * additions or deletions in visible regions.
+     * @param shiftrecord
+     * @return
+     */
     public ShiftList compensateForEdits(ShiftList shiftrecord) {
       if (shiftrecord!=null) {
         Vector shifts = shiftrecord.shifts;
         if (shifts!=null && shifts.size()>0) {
+          int shifted=0;
           for (int i=0,j=shifts.size(); i<j; i++) {
-            int[] sh = (int[]) shifts.get(i);
-            compensateForEdit(sh[0], sh[1]);
+            int[] sh = (int[]) shifts.elementAt(i);
+            //compensateForEdit(shifted+sh[0], sh[1]);
+            compensateForDelEdits(shifted+sh[0], sh[1]);
+            shifted-=sh[1];
           }
         }
         return shiftrecord.getInverse();
@@ -218,6 +268,117 @@ public class ColumnSelection
       return null;
     }
     /**
+     * removes intersection of position,length ranges in deletions
+     * from the start,end regions marked in intervals.
+     * @param deletions
+     * @param intervals
+     * @return
+     */
+    private boolean pruneIntervalVector(Vector deletions, Vector intervals) {
+      boolean pruned=false;
+      int i=0,j=intervals.size()-1, s=0, t=deletions.size()-1;
+      int hr[]=(int[]) intervals.elementAt(i);
+      int sr[]=(int[]) deletions.elementAt(s);
+      while (i<=j && s<=t) {
+        boolean trailinghn=hr[1]>=sr[0];
+        if (!trailinghn) {
+          if (i<j)
+            hr=(int[]) intervals.elementAt(++i);
+          else
+            i++;
+          continue;
+        }
+        int endshift=sr[0]+sr[1]; // deletion ranges - -ve means an insert
+        if (endshift<hr[0] || endshift<sr[0]) { // leadinghc disjoint or not a deletion
+          if (s<t)
+            sr=(int[]) deletions.elementAt(++s);
+          else
+            s++;
+          continue;
+        }
+        boolean leadinghn=hr[0]>=sr[0];
+        boolean leadinghc=hr[0]<endshift;
+        boolean trailinghc=hr[1]<endshift;
+        if (leadinghn) {
+          if (trailinghc) {// deleted hidden region.
+            intervals.removeElementAt(i);
+            pruned=true;
+            j--;
+            if (i<=j)
+              hr=(int[]) intervals.elementAt(i);
+            continue;
+          }
+          if (leadinghc) {
+            hr[0]=endshift; // clip c terminal region
+            leadinghn=!leadinghn;
+            pruned=true;
+          }
+        }
+        if (!leadinghn) {
+          if (trailinghc) {
+            if (trailinghn) {
+              hr[1]=sr[0]-1;
+              pruned=true;
+            }
+          } else {
+            // sr contained in hr
+            if (s<t)
+              sr=(int[]) deletions.elementAt(++s);
+            else
+              s++;
+            continue;
+          }
+        }
+      }
+      return pruned; // true if any interval was removed or modified by operations.
+    }
+    private boolean pruneColumnList(Vector deletion, Vector list) {
+      int s=0,t=deletion.size();
+      int[] sr=(int[])list.elementAt(s++);
+      boolean pruned=false;
+      int i=0, j=list.size();
+      while (i<j && s<=t) {
+        int c=((Integer)list.elementAt(i++)).intValue();
+        if (sr[0]<=c) {
+          if (sr[1]+sr[0]>=c) { // sr[1] -ve means inseriton.
+            list.removeElementAt(--i);
+            j--;
+          } else {
+            if (s<t)
+              sr = (int[])deletion.elementAt(s);
+            s++;
+          }
+        }
+      }
+      return pruned;
+    }
+    /**
+     * remove any hiddenColumns or selected columns and shift remaining
+     * based on a series of position, range deletions.
+     * @param deletions
+     */
+    public void pruneDeletions(ShiftList deletions) {
+      if (deletions!=null) {
+        Vector shifts=deletions.shifts;
+        if (shifts!=null && shifts.size()>0) {
+          // delete any intervals intersecting.
+          if (hiddenColumns!=null) {
+            pruneIntervalVector(shifts, hiddenColumns);
+            if (hiddenColumns!=null && hiddenColumns.size()==0) {
+              hiddenColumns=null;
+            }
+          }
+          if (selected!=null && selected.size()>0) {
+            pruneColumnList(shifts, selected);
+            if (selected!=null && selected.size()==0)
+              selected=null;
+          }
+          // and shift the rest.
+          this.compensateForEdits(deletions);
+        }
+      }
+    }
+    /**
      * This Method is used to return all the HiddenColumn regions
      * less than the given index.
      * @param end int
@@ -483,18 +644,18 @@ public class ColumnSelection
         if (copy.selected!=null) {
           selected = new Vector();
           for (int i=0,j=copy.selected.size(); i<j; i++) {
-            selected.set(i, ((Integer) copy.selected.get(i)));
+            selected.setElementAt( ((Integer) copy.selected.elementAt(i)), i);
           }
         }
         if (copy.hiddenColumns!=null) {
           hiddenColumns=new Vector();
           for (int i=0,j=copy.hiddenColumns.size(); i<j; i++) {
             int[] rh,cp;
-            rh = (int[])copy.hiddenColumns.get(i);
+            rh = (int[])copy.hiddenColumns.elementAt(i);
             if (rh!=null) {
               cp = new int[rh.length];
               System.arraycopy(rh, 0, cp, 0, rh.length);
-              hiddenColumns.set(i, cp);
+              hiddenColumns.setElementAt(cp, i);
             }
           }
         }
@@ -507,4 +668,61 @@ public class ColumnSelection
   public ColumnSelection()
   {
   }
+
+  public String[] getVisibleSequenceStrings(int start, int end, SequenceI[] seqs) {
+    int i,iSize=seqs.length;
+    String selection[] = new String[iSize];
+    if (hiddenColumns!=null && hiddenColumns.size()>0)
+      {
+      for (i=0; i<iSize; i++) {
+        StringBuffer visibleSeq = new StringBuffer();
+        Vector regions = getHiddenColumns();
+
+        int blockStart = start, blockEnd=end;
+        int [] region;
+           int hideStart, hideEnd;
+
+           for (int j = 0; j < regions.size(); j++)
+           {
+             region = (int[]) regions.elementAt(j);
+             hideStart = region[0];
+             hideEnd = region[1];
+
+             if(hideStart < start)
+             {
+               continue;
+             }
+
+             blockStart = Math.min(blockStart, hideEnd+1);
+             blockEnd = Math.min(blockEnd, hideStart);
+
+             if(blockStart>blockEnd)
+             {
+                break;
+             }
+
+
+             visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));
+
+             blockStart = hideEnd+1;
+             blockEnd = end;
+           }
+
+           if(end>blockStart)
+             visibleSeq.append(seqs[i].getSequence(blockStart, end));
+
+           selection[i] = visibleSeq.toString();
+        }
+      }
+      else
+      {
+        for(i=0; i<iSize; i++)
+        {
+        selection[i] = seqs[i].getSequence(start, end);
+        }
+      }
+      
+    return selection;
+    }
+  
 }