Remove left, right, empty cols work on hidden reps
[jalview.git] / src / jalview / datamodel / Alignment.java
index 61735ee..c0c4ae0 100755 (executable)
@@ -24,21 +24,23 @@ import jalview.util.*;
 \r
 import java.util.*;\r
 \r
-\r
 /** Data structure to hold and manipulate a multiple sequence alignment\r
  */\r
 public class Alignment implements AlignmentI\r
 {\r
+    protected Alignment dataset;\r
     protected Vector sequences;\r
     protected Vector groups = new Vector();\r
-    protected Vector superGroup = new Vector();\r
     protected char gapCharacter = '-';\r
+    protected int type = NUCLEOTIDE;\r
+    public static final int PROTEIN = 0;\r
+    public static final int NUCLEOTIDE = 1;\r
 \r
     /** DOCUMENT ME!! */\r
     public AlignmentAnnotation[] annotations;\r
 \r
-    /** DOCUMENT ME!! */\r
-    public boolean featuresAdded = false;\r
+    HiddenSequences hiddenSequences = new HiddenSequences(this);\r
+\r
 \r
     /** Make an alignment from an array of Sequences.\r
      *\r
@@ -46,14 +48,19 @@ public class Alignment implements AlignmentI
      */\r
     public Alignment(SequenceI[] seqs)\r
     {\r
+        int i=0;\r
+\r
+        if( jalview.util.Comparison.isNucleotide(seqs))\r
+          type = NUCLEOTIDE;\r
+        else\r
+          type = PROTEIN;\r
+\r
         sequences = new Vector();\r
 \r
-        for (int i = 0; i < seqs.length; i++)\r
+        for (i = 0; i < seqs.length; i++)\r
         {\r
             sequences.addElement(seqs[i]);\r
         }\r
-\r
-        getWidth();\r
     }\r
 \r
     /**\r
@@ -66,6 +73,16 @@ public class Alignment implements AlignmentI
         return sequences;\r
     }\r
 \r
+    public SequenceI [] getSequencesArray()\r
+    {\r
+      SequenceI [] reply = new SequenceI[sequences.size()];\r
+      for(int i=0; i<sequences.size(); i++)\r
+      {\r
+        reply[i] = (SequenceI)sequences.elementAt(i);\r
+      }\r
+      return reply;\r
+    }\r
+\r
     /**\r
      * DOCUMENT ME!\r
      *\r
@@ -89,22 +106,30 @@ public class Alignment implements AlignmentI
      */\r
     public void addSequence(SequenceI snew)\r
     {\r
-        sequences.addElement(snew);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param seq DOCUMENT ME!\r
-     */\r
-    public void addSequence(SequenceI[] seq)\r
-    {\r
-        for (int i = 0; i < seq.length; i++)\r
+      if(dataset!=null)\r
+      {\r
+        if(snew.getDatasetSequence()!=null)\r
+        {\r
+          System.out.println(snew.getName());\r
+          getDataset().addSequence(snew.getDatasetSequence());\r
+        }\r
+        else\r
         {\r
-            addSequence(seq[i]);\r
+          Sequence ds = new Sequence(snew.getName(),\r
+                                     AlignSeq.extractGaps("-. ",\r
+              snew.getSequence()),\r
+                                     snew.getStart(),\r
+                                     snew.getEnd());\r
+\r
+          snew.setDatasetSequence(ds);\r
+          getDataset().addSequence(ds);\r
         }\r
+      }\r
+\r
+      sequences.addElement(snew);\r
     }\r
 \r
+\r
     /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
      *\r
      * @param snew\r
@@ -131,64 +156,78 @@ public class Alignment implements AlignmentI
      */\r
     public void removeGaps()\r
     {\r
+        SequenceI[] seqs = getVisibleAndRepresentedSeqs();\r
+        int j, jSize = seqs.length;\r
+\r
         SequenceI current;\r
-        int iSize = getWidth();\r
+        int width = 0;\r
+        for (int i = 0; i < jSize; i++)\r
+        {\r
+          if (seqs[i].getLength() > width)\r
+          {\r
+            width = seqs[i].getLength();\r
+          }\r
+        }\r
 \r
-        for (int i = 0; i < iSize; i++)\r
+        int startCol = -1, endCol = -1;\r
+        boolean delete = true;\r
+        for (int i = 0; i < width; i++)\r
         {\r
-            boolean delete = true;\r
+            delete = true;\r
 \r
-            for (int j = 0; j < getHeight(); j++)\r
+            for (j = 0; j < jSize; j++)\r
             {\r
                 current = getSequenceAt(j);\r
 \r
                 if (current.getLength() > i)\r
                 {\r
-                    /* MC Should move this to a method somewhere */\r
                     if (!jalview.util.Comparison.isGap(current.getCharAt(i)))\r
                     {\r
+                        if(delete)\r
+                          endCol = i;\r
+\r
                         delete = false;\r
+                        break;\r
                     }\r
                 }\r
+\r
+            }\r
+\r
+            if(delete && startCol==-1)\r
+            {\r
+              startCol = i;\r
             }\r
 \r
-            if (delete)\r
+\r
+            if (!delete && startCol > -1)\r
             {\r
-                deleteColumns(i, i);\r
-                iSize--;\r
-                i--;\r
+              deleteColumns(seqs, startCol, endCol);\r
+              width -= (endCol - startCol);\r
+              i -= (endCol - startCol);\r
+              startCol = -1;\r
+              endCol = -1;\r
             }\r
         }\r
+\r
+        if (delete && startCol > -1)\r
+        {\r
+          deleteColumns(seqs, startCol, endCol);\r
+        }\r
+\r
     }\r
 \r
     /** Removes a range of columns (start to end inclusive).\r
      *\r
+     * @param seqs Sequences to remove columns from\r
      * @param start Start column in the alignment\r
      * @param end End column in the alignment\r
      */\r
-    public void deleteColumns(int start, int end)\r
+    public void deleteColumns(SequenceI [] seqs, int start, int end)\r
     {\r
-        deleteColumns(0, getHeight() - 1, start, end);\r
+      for(int i=0; i<seqs.length; i++)\r
+        seqs[i].deleteChars(start, end);\r
     }\r
 \r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param seq1 DOCUMENT ME!\r
-     * @param seq2 DOCUMENT ME!\r
-     * @param start DOCUMENT ME!\r
-     * @param end DOCUMENT ME!\r
-     */\r
-    public void deleteColumns(int seq1, int seq2, int start, int end)\r
-    {\r
-        for (int i = 0; i <= (end - start); i++)\r
-        {\r
-            for (int j = seq1; j <= seq2; j++)\r
-            {\r
-                getSequenceAt(j).deleteCharAt(start);\r
-            }\r
-        }\r
-    }\r
 \r
     /**\r
      * DOCUMENT ME!\r
@@ -197,13 +236,23 @@ public class Alignment implements AlignmentI
      */\r
     public void trimLeft(int i)\r
     {\r
-        for (int j = 0; j < getHeight(); j++)\r
+        SequenceI[] seqs = getVisibleAndRepresentedSeqs();\r
+        int j, jSize = seqs.length;\r
+        for (j = 0; j < jSize; j++)\r
         {\r
-            SequenceI s = getSequenceAt(j);\r
-            int newstart = s.findPosition(i);\r
+            int newstart = seqs[j].findPosition(i);\r
 \r
-            s.setStart(newstart);\r
-            s.setSequence(s.getSequence().substring(i));\r
+            if(i>seqs[j].getLength())\r
+            {\r
+              sequences.removeElement(seqs[j]);\r
+              j--;\r
+              jSize--;\r
+            }\r
+            else\r
+            {\r
+              seqs[j].setStart(newstart);\r
+              seqs[j].setSequence(seqs[j].getSequence().substring(i));\r
+            }\r
         }\r
     }\r
 \r
@@ -214,13 +263,15 @@ public class Alignment implements AlignmentI
      */\r
     public void trimRight(int i)\r
     {\r
-        for (int j = 0; j < getHeight(); j++)\r
+        SequenceI[] seqs = getVisibleAndRepresentedSeqs();\r
+        int j, jSize = seqs.length;\r
+        for (j = 0; j < jSize; j++)\r
         {\r
-            SequenceI s = getSequenceAt(j);\r
-            int newend = s.findPosition(i);\r
+            int newend = seqs[j].findPosition(i);\r
 \r
-            s.setEnd(newend);\r
-            s.setSequence(s.getSequence().substring(0, i + 1));\r
+            seqs[j].setEnd(newend);\r
+            if(seqs[j].getLength()>i)\r
+              seqs[j].setSequence(seqs[j].getSequence().substring(0, i + 1));\r
         }\r
     }\r
 \r
@@ -250,62 +301,6 @@ public class Alignment implements AlignmentI
         sequences.removeElementAt(i);\r
     }\r
 \r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param threshold DOCUMENT ME!\r
-     * @param sel DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public Vector removeRedundancy(float threshold, Vector sel)\r
-    {\r
-        Vector del = new Vector();\r
-\r
-        for (int i = 1; i < sel.size(); i++)\r
-        {\r
-            for (int j = 0; j < i; j++)\r
-            {\r
-                // Only do the comparison if either have not been deleted\r
-                if (!del.contains((SequenceI) sel.elementAt(i)) ||\r
-                        !del.contains((SequenceI) sel.elementAt(j)))\r
-                {\r
-                    // use PID instead of Comparison (which is really not pleasant)\r
-                    float pid = Comparison.PID((SequenceI) sel.elementAt(j),\r
-                            (SequenceI) sel.elementAt(i));\r
-\r
-                    if (pid >= threshold)\r
-                    {\r
-                        // Delete the shortest one\r
-                        if (((SequenceI) sel.elementAt(j)).getSequence().length() > ((SequenceI) sel\r
-                                                                                         .elementAt(\r
-                                    i)).getSequence().length())\r
-                        {\r
-                            del.addElement(sel.elementAt(i));\r
-                        }\r
-                        else\r
-                        {\r
-                            del.addElement(sel.elementAt(i));\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        // Now delete the sequences\r
-        for (int i = 0; i < del.size(); i++)\r
-        {\r
-            deleteSequence((SequenceI) del.elementAt(i));\r
-        }\r
-\r
-        return del;\r
-    }\r
-\r
-    /**    */\r
-    public SequenceGroup findGroup(int i)\r
-    {\r
-        return findGroup(getSequenceAt(i));\r
-    }\r
 \r
     /**    */\r
     public SequenceGroup findGroup(SequenceI s)\r
@@ -314,7 +309,7 @@ public class Alignment implements AlignmentI
         {\r
             SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
 \r
-            if (sg.sequences.contains(s))\r
+            if (sg.getSequences(false).contains(s))\r
             {\r
                 return sg;\r
             }\r
@@ -338,14 +333,14 @@ public class Alignment implements AlignmentI
         for (int i = 0; i < gSize; i++)\r
         {\r
             SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
-            if(sg==null || sg.sequences==null)\r
+            if(sg==null || sg.getSequences(false)==null)\r
             {\r
               this.deleteGroup(sg);\r
               gSize--;\r
               continue;\r
             }\r
 \r
-            if (sg.sequences.contains(s))\r
+            if (sg.getSequences(false).contains(s))\r
             {\r
                 temp.addElement(sg);\r
             }\r
@@ -361,47 +356,7 @@ public class Alignment implements AlignmentI
         return ret;\r
     }\r
 \r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param sg DOCUMENT ME!\r
-     */\r
-    public void addSuperGroup(SuperGroup sg)\r
-    {\r
-        superGroup.addElement(sg);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param sg DOCUMENT ME!\r
-     */\r
-    public void removeSuperGroup(SuperGroup sg)\r
-    {\r
-        superGroup.removeElement(sg);\r
-    }\r
-\r
-    /**\r
-     * DOCUMENT ME!\r
-     *\r
-     * @param sg DOCUMENT ME!\r
-     *\r
-     * @return DOCUMENT ME!\r
-     */\r
-    public SuperGroup getSuperGroup(SequenceGroup sg)\r
-    {\r
-        for (int i = 0; i < this.superGroup.size(); i++)\r
-        {\r
-            SuperGroup temp = (SuperGroup) superGroup.elementAt(i);\r
-\r
-            if (temp.sequenceGroups.contains(sg))\r
-            {\r
-                return temp;\r
-            }\r
-        }\r
 \r
-        return null;\r
-    }\r
 \r
     /**    */\r
     public void addGroup(SequenceGroup sg)\r
@@ -418,7 +373,6 @@ public class Alignment implements AlignmentI
     public void deleteAllGroups()\r
     {\r
         groups.removeAllElements();\r
-        superGroup.removeAllElements();\r
 \r
         int i = 0;\r
 \r
@@ -446,11 +400,9 @@ public class Alignment implements AlignmentI
 \r
         while (i < sequences.size())\r
         {\r
-            SequenceI s = getSequenceAt(i);\r
-\r
-            if (s.getName().equals(name))\r
+            if (getSequenceAt(i).getName().equals(name))\r
             {\r
-                return s;\r
+                return getSequenceAt(i);\r
             }\r
 \r
             i++;\r
@@ -459,25 +411,6 @@ public class Alignment implements AlignmentI
         return null;\r
     }\r
 \r
-    /**    */\r
-    public SequenceI findbyDisplayId(String name)\r
-    {\r
-        int i = 0;\r
-\r
-        while (i < sequences.size())\r
-        {\r
-            SequenceI s = getSequenceAt(i);\r
-\r
-            if (s.getDisplayId().equals(name))\r
-            {\r
-                return s;\r
-            }\r
-\r
-            i++;\r
-        }\r
-\r
-        return null;\r
-    }\r
 \r
     /**    */\r
     public int findIndex(SequenceI s)\r
@@ -566,9 +499,9 @@ public class Alignment implements AlignmentI
         for (int i = 0; i < sequences.size(); i++)\r
         {\r
             Sequence seq = (Sequence) sequences.elementAt(i);\r
-            seq.sequence = seq.sequence.replace('.', gc);\r
-            seq.sequence = seq.sequence.replace('-', gc);\r
-            seq.sequence = seq.sequence.replace(' ', gc);\r
+            seq.setSequence( seq.getSequence().replace('.', gc) );\r
+            seq.setSequence( seq.getSequence().replace('-', gc) );\r
+            seq.setSequence( seq.getSequence().replace(' ', gc) );\r
         }\r
     }\r
 \r
@@ -644,6 +577,21 @@ public class Alignment implements AlignmentI
         annotations = temp;\r
     }\r
 \r
+\r
+    public void adjustSequenceAnnotations()\r
+    {\r
+      if(annotations!=null)\r
+      {\r
+        for (int a = 0; a < annotations.length; a++)\r
+        {\r
+          if (annotations[a].sequenceRef != null)\r
+          {\r
+            annotations[a].adjustForAlignment();\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
     /**\r
      * DOCUMENT ME!\r
      *\r
@@ -652,24 +600,48 @@ public class Alignment implements AlignmentI
     public void addAnnotation(AlignmentAnnotation aa)\r
     {\r
         int aSize = 1;\r
-\r
         if (annotations != null)\r
         {\r
             aSize = annotations.length + 1;\r
         }\r
 \r
         AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];\r
+\r
+        temp[aSize-1] = aa;\r
+\r
         int i = 0;\r
 \r
         if (aSize > 1)\r
         {\r
-            for (i = 0; i < (aSize - 1); i++)\r
+            for (i = 0; i < (aSize-1); i++)\r
             {\r
                 temp[i] = annotations[i];\r
             }\r
         }\r
 \r
-        temp[i] = aa;\r
+        annotations = temp;\r
+    }\r
+\r
+    public void setAnnotationIndex(AlignmentAnnotation aa, int index)\r
+    {\r
+      if(aa==null || annotations==null || annotations.length-1<index)\r
+        return;\r
+\r
+      int aSize = annotations.length;\r
+      AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];\r
+\r
+      temp[index] = aa;\r
+\r
+      for (int i = 0; i < aSize; i++)\r
+      {\r
+        if(i==index)\r
+          continue;\r
+\r
+        if(i<index)\r
+          temp[i] = annotations[i];\r
+        else\r
+          temp[i] = annotations[i-1];\r
+      }\r
 \r
         annotations = temp;\r
     }\r
@@ -683,4 +655,137 @@ public class Alignment implements AlignmentI
     {\r
         return annotations;\r
     }\r
+\r
+    public void setNucleotide(boolean b)\r
+    {\r
+      if(b)\r
+        type = NUCLEOTIDE;\r
+      else\r
+        type = PROTEIN;\r
+    }\r
+\r
+    public boolean isNucleotide()\r
+    {\r
+      if(type==NUCLEOTIDE)\r
+        return true;\r
+      else\r
+        return false;\r
+    }\r
+\r
+    public void setDataset(Alignment data)\r
+    {\r
+      if(dataset==null && data==null)\r
+      {\r
+        // Create a new dataset for this alignment.\r
+        // Can only be done once, if dataset is not null\r
+        // This will not be performed\r
+        Sequence[] seqs = new Sequence[getHeight()];\r
+        for (int i = 0; i < getHeight(); i++)\r
+        {\r
+          if(getSequenceAt(i).getDatasetSequence()!=null)\r
+          {\r
+            seqs[i] = (Sequence)getSequenceAt(i).getDatasetSequence();\r
+          }\r
+          else\r
+          {\r
+            seqs[i] = new Sequence(getSequenceAt(i).getName(),\r
+                                   AlignSeq.extractGaps(\r
+                                       jalview.util.Comparison.GapChars,\r
+                                       getSequenceAt(i).getSequence()\r
+                                   ),\r
+                                   getSequenceAt(i).getStart(),\r
+                                   getSequenceAt(i).getEnd());\r
+\r
+            getSequenceAt(i).setDatasetSequence(seqs[i]);\r
+          }\r
+        }\r
+\r
+        dataset = new Alignment(seqs);\r
+      }\r
+      else if(dataset==null && data!=null)\r
+      {\r
+        dataset = data;\r
+      }\r
+    }\r
+\r
+    public Alignment getDataset()\r
+    {\r
+      return dataset;\r
+    }\r
+\r
+    public boolean padGaps() {\r
+      boolean modified=false;\r
+\r
+      //Remove excess gaps from the end of alignment\r
+      int maxLength = -1;\r
+\r
+      SequenceI current;\r
+      for (int i = 0; i < sequences.size(); i++)\r
+      {\r
+        current = getSequenceAt(i);\r
+        for (int j = current.getLength(); j > maxLength; j--)\r
+        {\r
+          if (j > maxLength && !jalview.util.Comparison.isGap(\r
+              current.getCharAt(j)))\r
+          {\r
+            maxLength = j;\r
+            break;\r
+          }\r
+        }\r
+      }\r
+\r
+      maxLength++;\r
+\r
+      for (int i = 0; i < sequences.size();\r
+           i++)\r
+      {\r
+        current = getSequenceAt(i);\r
+\r
+        if (current.getLength() < maxLength)\r
+        {\r
+          current.insertCharAt(maxLength - 1, gapCharacter);\r
+          modified=true;\r
+        }\r
+        else if(current.getLength() > maxLength)\r
+        {\r
+          current.deleteChars(maxLength, current.getLength());\r
+        }\r
+      }\r
+      return modified;\r
+    }\r
+\r
+    public HiddenSequences getHiddenSequences()\r
+    {\r
+      return hiddenSequences;\r
+    }\r
+\r
+    SequenceI [] getVisibleAndRepresentedSeqs()\r
+    {\r
+      if(hiddenSequences==null || hiddenSequences.getSize()<1)\r
+        return getSequencesArray();\r
+\r
+      Vector seqs = new Vector();\r
+      SequenceI seq;\r
+      SequenceGroup hidden;\r
+      for (int i = 0; i < sequences.size(); i++)\r
+      {\r
+        seq = (SequenceI) sequences.elementAt(i);\r
+        seqs.addElement(seq);\r
+        hidden = seq.getHiddenSequences();\r
+        if(hidden!=null)\r
+        {\r
+          for(int j=0; j<hidden.getSize(false); j++)\r
+          {\r
+            seqs.addElement(hidden.getSequenceAt(j));\r
+          }\r
+        }\r
+      }\r
+      SequenceI [] result = new SequenceI[seqs.size()];\r
+      for(int i=0; i<seqs.size(); i++)\r
+        result[i] = (SequenceI)seqs.elementAt(i);\r
+\r
+      return result;\r
+\r
+    }\r
+\r
 }\r