Don't parse input id, leave it as it is
[jalview.git] / src / jalview / datamodel / Alignment.java
index 9b6d729..3a1b44a 100755 (executable)
+/*\r
+ * Jalview - A Sequence Alignment Editor and Viewer\r
+ * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
+ */\r
 package jalview.datamodel;\r
 \r
 import jalview.analysis.*;\r
+\r
 import jalview.util.*;\r
+\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 Provenance provenance;\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
+\r
+    /** Make an alignment from an array of Sequences.\r
+     *\r
+     * @param sequences\r
+     */\r
+    public Alignment(SequenceI[] seqs)\r
+    {\r
+        int i=0;\r
 \r
-  protected Vector      sequences;\r
-  protected Vector      groups = new Vector();\r
-  public    Hashtable[] cons;\r
-  protected String      gapCharacter = ".";\r
-\r
-  /** Make an alignment from an array of Sequences.\r
-  *\r
-  * @param sequences\r
-  */\r
-  public Alignment(SequenceI[] seqs) {\r
-    sequences = new Vector();\r
-\r
-    for (int i=0; i < seqs.length; i++)\r
-      sequences.addElement(seqs[i]);\r
+        if( jalview.util.Comparison.isNucleotide(seqs))\r
+          type = NUCLEOTIDE;\r
+        else\r
+          type = PROTEIN;\r
 \r
-    SequenceGroup all = new SequenceGroup();\r
-    all.setName("Group 1");\r
-    groups.addElement(all);\r
+        sequences = new Vector();\r
 \r
-    int i = 0;\r
+        for (i = 0; i < seqs.length; i++)\r
+        {\r
+            sequences.addElement(seqs[i]);\r
+        }\r
 \r
-    while (i < seqs.length) {\r
-      addToGroup(all,seqs[i]);\r
-      i++;\r
+        getWidth();\r
     }\r
 \r
-    getWidth();\r
-  }\r
-\r
-  public Vector      getSequences() {\r
-    return sequences;\r
-  }\r
-\r
-  public SequenceI getSequenceAt(int i) {\r
-    if (i < sequences.size()) {\r
-      return (SequenceI)sequences.elementAt(i);\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public Vector getSequences()\r
+    {\r
+        return sequences;\r
     }\r
 \r
-    return null;\r
-  }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param i DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public SequenceI getSequenceAt(int i)\r
+    {\r
+        if (i < sequences.size())\r
+        {\r
+            return (SequenceI) sequences.elementAt(i);\r
+        }\r
 \r
-  /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
-   * Should put the new sequence in a sequence group!!!\r
-   *\r
-   * @param snew\r
-   */\r
-  public void addSequence(SequenceI snew) {\r
-    sequences.addElement(snew);\r
+        return null;\r
+    }\r
 \r
-    ((SequenceGroup)groups.lastElement()).addSequence(snew);\r
-  }\r
+    /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
+     *\r
+     * @param snew\r
+     */\r
+    public void addSequence(SequenceI snew)\r
+    {\r
+        sequences.addElement(snew);\r
+    }\r
 \r
-  public void addSequence(SequenceI[] seq) {\r
-    for (int i=0; i < seq.length; i++) {\r
-      addSequence(seq[i]);\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
+        {\r
+            addSequence(seq[i]);\r
+        }\r
     }\r
-  }\r
 \r
-  /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
-   * Should put the new sequence in a sequence group!!!\r
-   *\r
-   * @param snew\r
-   */\r
-  public void setSequenceAt(int i,SequenceI snew) {\r
-    SequenceI oldseq = getSequenceAt(i);\r
-    deleteSequence(oldseq);\r
+    /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
+     *\r
+     * @param snew\r
+     */\r
+    public void setSequenceAt(int i, SequenceI snew)\r
+    {\r
+        SequenceI oldseq = getSequenceAt(i);\r
+        deleteSequence(oldseq);\r
 \r
-    sequences.setElementAt(snew,i);\r
+        sequences.setElementAt(snew, i);\r
+    }\r
 \r
-    ((SequenceGroup)groups.lastElement()).addSequence(snew);\r
-  }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public Vector getGroups()\r
+    {\r
+        return groups;\r
+    }\r
 \r
-  public Vector getGroups() {\r
-    return groups;\r
-  }\r
+    /** Takes out columns consisting entirely of gaps (-,.," ")\r
+     */\r
+    public void removeGaps()\r
+    {\r
+        SequenceI current;\r
+        int iSize = getWidth();\r
 \r
-  /** Sorts the sequences by sequence group size - largest to smallest.\r
-   * Uses QuickSort.\r
-   */\r
-  public void sortGroups() {\r
-    float[]  arr = new float [groups.size()];\r
-    Object[] s   = new Object[groups.size()];\r
+        for (int i = 0; i < iSize; i++)\r
+        {\r
+            boolean delete = true;\r
+\r
+            for (int j = 0; j < getHeight(); 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
+                        delete = false;\r
+                    }\r
+                }\r
+            }\r
 \r
-    for (int i=0; i < groups.size(); i++) {\r
-      arr[i] = ((SequenceGroup)groups.elementAt(i)).sequences.size();\r
-      s[i]   = groups.elementAt(i);\r
+            if (delete)\r
+            {\r
+                deleteColumns(i, i);\r
+                iSize--;\r
+                i--;\r
+            }\r
+        }\r
     }\r
 \r
-    QuickSort.sort(arr,s);\r
-\r
-    Vector newg = new Vector(groups.size());\r
+    /** Removes a range of columns (start to end inclusive).\r
+     *\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
+    {\r
+        deleteColumns(0, getHeight() - 1, start, end);\r
+    }\r
 \r
-    for (int i=groups.size()-1; i >= 0; i--) {\r
-      newg.addElement(s[i]);\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
-    groups = newg;\r
-  }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param i DOCUMENT ME!\r
+     */\r
+    public void trimLeft(int i)\r
+    {\r
+        for (int j = 0; j < getHeight(); j++)\r
+        {\r
+            SequenceI s = getSequenceAt(j);\r
+            int newstart = s.findPosition(i);\r
 \r
-  /** Takes out columns consisting entirely of gaps (-,.," ")\r
-   */\r
-  public void removeGaps()\r
-  {\r
+            s.setStart(newstart);\r
+            s.setSequence(s.getSequence().substring(i));\r
+        }\r
+    }\r
 \r
-    SequenceI current;\r
-    int iSize = getWidth();\r
-    for (int i=0; i < iSize; i++)\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param i DOCUMENT ME!\r
+     */\r
+    public void trimRight(int i)\r
     {\r
-      boolean delete = true;\r
-      for (int j=0; j < getHeight(); j++)\r
-      {\r
-        current = getSequenceAt(j);\r
-        if (current.getLength() > i)\r
+        for (int j = 0; j < getHeight(); j++)\r
         {\r
-           /* MC Should move this to a method somewhere */\r
-          if (current.getCharAt(i)!='-' && current.getCharAt(i)!='.' && current.getCharAt(i)!=' ')\r
-            delete = false;\r
+            SequenceI s = getSequenceAt(j);\r
+            int newend = s.findPosition(i);\r
 \r
+            s.setEnd(newend);\r
+            s.setSequence(s.getSequence().substring(0, i + 1));\r
         }\r
-      }\r
+    }\r
 \r
-      if ( delete )\r
-      {\r
-        deleteColumns(i,i);\r
-        iSize--;\r
-        i--;\r
-      }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param s DOCUMENT ME!\r
+     */\r
+    public void deleteSequence(SequenceI s)\r
+    {\r
+        for (int i = 0; i < getHeight(); i++)\r
+        {\r
+            if (getSequenceAt(i) == s)\r
+            {\r
+                deleteSequence(i);\r
+            }\r
+        }\r
     }\r
 \r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param i DOCUMENT ME!\r
+     */\r
+    public void deleteSequence(int i)\r
+    {\r
+        sequences.removeElementAt(i);\r
+    }\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
-  /** Returns an array of Sequences containing columns\r
-   * start to end (inclusive) only.\r
-   *\r
-   * @param start start column to fetch\r
-   * @param end end column to fetch\r
-   * @return Array of Sequences, ready to put into a new Alignment\r
-   */\r
-  public SequenceI[] getColumns(int start, int end) {\r
-    return getColumns(0,getHeight()-1,start,end);\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
-  /** Removes a range of columns (start to end inclusive).\r
-   *\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
-    deleteColumns(0,getHeight()-1,start,end);\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
-  public void deleteColumns(int seq1, int seq2, int start, int end) {\r
+        return del;\r
+    }\r
 \r
-    for (int i=0; i <= (end-start); i++) {\r
-      for (int j=seq1; j <= seq2; j++) {\r
-        getSequenceAt(j).deleteCharAt(start);\r
-      }\r
+    /**    */\r
+    public SequenceGroup findGroup(int i)\r
+    {\r
+        return findGroup(getSequenceAt(i));\r
     }\r
-  }\r
 \r
-  public void insertColumns(SequenceI[] seqs, int pos) {\r
-    if (seqs.length == getHeight()) {\r
-      for (int i=0; i < getHeight();i++) {\r
-        String tmp = new String(getSequenceAt(i).getSequence());\r
-        getSequenceAt(i).setSequence(tmp.substring(0,pos) + seqs[i].getSequence() + tmp.substring(pos));\r
-      }\r
+    /**    */\r
+    public SequenceGroup findGroup(SequenceI s)\r
+    {\r
+        for (int i = 0; i < this.groups.size(); i++)\r
+        {\r
+            SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
 \r
-    }\r
-  }\r
+            if (sg.sequences.contains(s))\r
+            {\r
+                return sg;\r
+            }\r
+        }\r
 \r
-  public SequenceI[] getColumns(int seq1, int seq2, int start, int end) {\r
-    SequenceI[] seqs = new Sequence[(seq2-seq1)+1];\r
-    for (int i=seq1; i<= seq2; i++ ) {\r
-      seqs[i] = new Sequence(getSequenceAt(i).getName(),\r
-                             getSequenceAt(i).getSequence().substring(start,end),\r
-                             getSequenceAt(i).findPosition(start),\r
-                             getSequenceAt(i).findPosition(end));\r
+        return null;\r
     }\r
-    return seqs;\r
-  }\r
 \r
-  public void trimLeft(int i) {\r
-    for (int j = 0;j< getHeight();j++) {\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param s DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public SequenceGroup[] findAllGroups(SequenceI s)\r
+    {\r
+        Vector temp = new Vector();\r
 \r
-      SequenceI s        = getSequenceAt(j);\r
-      int       newstart = s.findPosition(i);\r
+        int gSize = groups.size();\r
+        for (int i = 0; i < gSize; i++)\r
+        {\r
+            SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
+            if(sg==null || sg.sequences==null)\r
+            {\r
+              this.deleteGroup(sg);\r
+              gSize--;\r
+              continue;\r
+            }\r
 \r
-      s.setStart(newstart);\r
-      s.setSequence(s.getSequence().substring(i));\r
+            if (sg.sequences.contains(s))\r
+            {\r
+                temp.addElement(sg);\r
+            }\r
+        }\r
 \r
+        SequenceGroup[] ret = new SequenceGroup[temp.size()];\r
+\r
+        for (int i = 0; i < temp.size(); i++)\r
+        {\r
+            ret[i] = (SequenceGroup) temp.elementAt(i);\r
+        }\r
+\r
+        return ret;\r
     }\r
-  }\r
 \r
-  public void  trimRight(int i) {\r
-    for (int j = 0;j< getHeight();j++) {\r
-      SequenceI s      = getSequenceAt(j);\r
-      int       newend = s.findPosition(i);\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
-      s.setEnd(newend);\r
-      s.setSequence(s.getSequence().substring(0,i+1));\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
-  public void deleteSequence(SequenceI s)\r
-  {\r
-    for (int i=0; i < getHeight(); i++)\r
-      if (getSequenceAt(i) == s)\r
-        deleteSequence(i);\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
-  public void  deleteSequence(int i)\r
-  {\r
-    sequences.removeElementAt(i);\r
-  }\r
+            if (temp.sequenceGroups.contains(sg))\r
+            {\r
+                return temp;\r
+            }\r
+        }\r
 \r
+        return null;\r
+    }\r
 \r
-  public Vector removeRedundancy(float threshold, Vector sel) {\r
-    Vector del = new Vector();\r
+    /**    */\r
+    public void addGroup(SequenceGroup sg)\r
+    {\r
+        if (!groups.contains(sg))\r
+        {\r
+            groups.addElement(sg);\r
+        }\r
+    }\r
 \r
-    for (int i=1; i < sel.size(); i++) {\r
-      for (int j = 0; j < i; j++) {\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
+     * DOCUMENT ME!\r
+     */\r
+    public void deleteAllGroups()\r
+    {\r
+        groups.removeAllElements();\r
+        superGroup.removeAllElements();\r
 \r
-          float pid = Comparison.compare((SequenceI)sel.elementAt(j),\r
-                                         (SequenceI)sel.elementAt(i));\r
+        int i = 0;\r
 \r
-          if (pid >= threshold) {\r
-            // Delete the shortest one\r
-            if (((SequenceI)sel.elementAt(j)).getSequence().length() >\r
-                ((SequenceI)sel.elementAt(i)).getSequence().length()) {\r
-              del.addElement(sel.elementAt(i));\r
-              System.out.println("Deleting sequence " + ((SequenceI)sel.elementAt(i)).getName());\r
-            } else {\r
-              del.addElement(sel.elementAt(i));\r
-              System.out.println("Deleting sequence " + ((SequenceI)sel.elementAt(i)).getName());\r
-            }\r
-          }\r
+        while (i < sequences.size())\r
+        {\r
+            SequenceI s = getSequenceAt(i);\r
+            s.setColor(java.awt.Color.white);\r
+            i++;\r
         }\r
-      }\r
     }\r
 \r
-    // Now delete the sequences\r
-    for (int i=0; i < del.size(); i++) {\r
-      System.out.println("Deleting sequence " + ((SequenceI)del.elementAt(i)).getName());\r
-      deleteSequence((SequenceI)del.elementAt(i));\r
+    /**    */\r
+    public void deleteGroup(SequenceGroup g)\r
+    {\r
+        if (groups.contains(g))\r
+        {\r
+            groups.removeElement(g);\r
+        }\r
     }\r
 \r
-    return del;\r
-  }\r
+    /**    */\r
+    public SequenceI findName(String name)\r
+    {\r
+        int i = 0;\r
 \r
-  public void sortByPID(SequenceI s) {\r
+        while (i < sequences.size())\r
+        {\r
+            if (getSequenceAt(i).getName().equals(name))\r
+            {\r
+                return getSequenceAt(i);\r
+            }\r
 \r
-    float     scores[] = new float[getHeight()];\r
-    SequenceI seqs[]   = new SequenceI[getHeight()];\r
+            i++;\r
+        }\r
 \r
-    for (int i = 0; i < getHeight(); i++) {\r
-      scores[i] = Comparison.compare(getSequenceAt(i),s);\r
-      seqs[i]   = getSequenceAt(i);\r
+        return null;\r
     }\r
 \r
-    QuickSort.sort(scores,0,scores.length-1,seqs);\r
 \r
-    int len = 0;\r
+    /**    */\r
+    public int findIndex(SequenceI s)\r
+    {\r
+        int i = 0;\r
+\r
+        while (i < sequences.size())\r
+        {\r
+            if (s == getSequenceAt(i))\r
+            {\r
+                return i;\r
+            }\r
+\r
+            i++;\r
+        }\r
 \r
-    if (getHeight()%2 == 0) {\r
-      len = getHeight()/2;\r
-    } else {\r
-      len = (getHeight()+1)/2;\r
+        return -1;\r
     }\r
 \r
-    for (int i = 0; i < len; i++) {\r
-      SequenceI tmp = seqs[i];\r
-      sequences.setElementAt(seqs[getHeight()-i-1],i);\r
-      sequences.setElementAt(tmp,getHeight()-i-1);\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public int getHeight()\r
+    {\r
+        return sequences.size();\r
     }\r
-  }\r
 \r
-  public void sortByID() {\r
-    String    ids[]   = new String[getHeight()];\r
-    SequenceI seqs[]  = new SequenceI[getHeight()];\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public int getWidth()\r
+    {\r
+        int maxLength = -1;\r
+\r
+        for (int i = 0; i < sequences.size(); i++)\r
+        {\r
+            if (getSequenceAt(i).getLength() > maxLength)\r
+            {\r
+                maxLength = getSequenceAt(i).getLength();\r
+            }\r
+        }\r
 \r
-    for (int i = 0; i < getHeight(); i++) {\r
-      ids[i]  = getSequenceAt(i).getName();\r
-      seqs[i] = getSequenceAt(i);\r
+        return maxLength;\r
     }\r
 \r
-    QuickSort.sort(ids,seqs);\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public int getMaxIdLength()\r
+    {\r
+        int max = 0;\r
+        int i = 0;\r
 \r
-    int len = 0;\r
+        while (i < sequences.size())\r
+        {\r
+            SequenceI seq = getSequenceAt(i);\r
+            String tmp = seq.getName() + "/" + seq.getStart() + "-" +\r
+                seq.getEnd();\r
 \r
-    if (getHeight()%2 == 0) {\r
-      len = getHeight()/2;\r
-    } else {\r
-      len = (getHeight()+1)/2;\r
-      System.out.println("Sort len is odd = " + len);\r
-    }\r
-    for (int i = 0; i < len; i++) {\r
-      System.out.println("Swapping " + seqs[i].getName() + " and " + seqs[getHeight()-i-1].getName());\r
-      SequenceI tmp = seqs[i];\r
-      sequences.setElementAt(seqs[getHeight()-i-1],i);\r
-      sequences.setElementAt(tmp,getHeight()-i-1);\r
-    }\r
-  }\r
+            if (tmp.length() > max)\r
+            {\r
+                max = tmp.length();\r
+            }\r
 \r
-  /**    */\r
-  public SequenceGroup findGroup(int i) {\r
-    return findGroup(getSequenceAt(i));\r
-  }\r
+            i++;\r
+        }\r
+\r
+        return max;\r
+    }\r
 \r
-  /**    */\r
-  public SequenceGroup findGroup(SequenceI s) {\r
-    for (int i = 0; i < this.groups.size();i++)\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param gc DOCUMENT ME!\r
+     */\r
+    public void setGapCharacter(char gc)\r
     {\r
-      SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
-      if (sg.sequences.contains(s))\r
-        return sg;\r
+        gapCharacter = gc;\r
 \r
+        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
+        }\r
     }\r
-    return null;\r
 \r
-  }\r
-  /**    */\r
-  public void addToGroup(SequenceGroup g, SequenceI s) {\r
-    if (!(g.sequences.contains(s))) {\r
-      g.sequences.addElement(s);\r
-    }\r
-  }\r
-  /**    */\r
-  public void removeFromGroup(SequenceGroup g,SequenceI s) {\r
-    if (g != null && g.sequences != null) {\r
-      if (g.sequences.contains(s)) {\r
-        g.sequences.removeElement(s);\r
-        if (g.sequences.size() == 0) {\r
-          groups.removeElement(g);\r
-        }\r
-      }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public char getGapCharacter()\r
+    {\r
+        return gapCharacter;\r
     }\r
-  }\r
-\r
-  /**    */\r
-  public void addGroup(SequenceGroup sg) {\r
-    groups.addElement(sg);\r
-  }\r
-\r
-  /**    */\r
-  public SequenceGroup addGroup() {\r
-    SequenceGroup sg = new SequenceGroup();\r
-    groups.addElement(sg);\r
-    return sg;\r
-  }\r
-\r
-  /**    */\r
-  public void deleteGroup(SequenceGroup g) {\r
-    if (groups.contains(g)) {\r
-      groups.removeElement(g);\r
-    }\r
-  }\r
-\r
-  /**    */\r
-  public SequenceI findName(String name) {\r
-    int i = 0;\r
-    while (i < sequences.size()) {\r
-      SequenceI s = getSequenceAt(i);\r
-      if (s.getName().equals(name))\r
-        return s;\r
-\r
-      i++;\r
-    }\r
-    return null;\r
-  }\r
-\r
-  /**    */\r
-  public SequenceI findbyDisplayId(String name) {\r
-    int i = 0;\r
-    while (i < sequences.size()) {\r
-      SequenceI s = getSequenceAt(i);\r
-      if (s.getDisplayId().equals(name))\r
-        return s;\r
-\r
-      i++;\r
-    }\r
-    return null;\r
-  }\r
-\r
-  /**    */\r
-  public int findIndex(SequenceI s) {\r
-    int i=0;\r
-    while (i < sequences.size()) {\r
-      if (s == getSequenceAt(i)) {\r
-        return i;\r
-      }\r
-      i++;\r
+\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public Vector getAAFrequency()\r
+    {\r
+        return AAFrequency.calculate(sequences, 0, getWidth());\r
     }\r
-    return -1;\r
-  }\r
 \r
-  public int getHeight() {\r
-    return sequences.size();\r
-  }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public boolean isAligned()\r
+    {\r
+        int width = getWidth();\r
 \r
+        for (int i = 0; i < sequences.size(); i++)\r
+        {\r
+            if (getSequenceAt(i).getLength() != width)\r
+            {\r
+                return false;\r
+            }\r
+        }\r
 \r
-  public int getWidth()\r
-  {\r
-    int maxLength = -1;\r
-    for (int i = 0; i < sequences.size(); i++)\r
-    {\r
-      if (getSequenceAt(i).getLength() > maxLength)\r
-        maxLength = getSequenceAt(i).getLength();\r
+        return true;\r
     }\r
 \r
-    return maxLength;\r
-  }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param aa DOCUMENT ME!\r
+     */\r
+    public void deleteAnnotation(AlignmentAnnotation aa)\r
+    {\r
+        int aSize = 1;\r
 \r
+        if (annotations != null)\r
+        {\r
+            aSize = annotations.length;\r
+        }\r
 \r
-  public int getMaxIdLength() {\r
-    int max = 0;\r
-    int i   = 0;\r
+        AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];\r
 \r
-    while (i < sequences.size()) {\r
-      SequenceI seq = getSequenceAt(i);\r
-      String    tmp = seq.getName() + "/" + seq.getStart() + "-" + seq.getEnd();\r
+        int tIndex = 0;\r
 \r
-      if (tmp.length() > max) {\r
-        max = tmp.length();\r
-      }\r
+        for (int i = 0; i < aSize; i++)\r
+        {\r
+            if (annotations[i] == aa)\r
+            {\r
+                continue;\r
+            }\r
+\r
+            temp[tIndex] = annotations[i];\r
+            tIndex++;\r
+        }\r
 \r
-      i++;\r
+        annotations = temp;\r
     }\r
-    return max;\r
-  }\r
 \r
-  public void setGapCharacter(String gc) {\r
-    gapCharacter = gc;\r
-  }\r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @param aa DOCUMENT ME!\r
+     */\r
+    public void addAnnotation(AlignmentAnnotation aa)\r
+    {\r
+        int aSize = 1;\r
 \r
-  public String getGapCharacter() {\r
-    return gapCharacter;\r
-  }\r
+        if (annotations != null)\r
+        {\r
+            aSize = annotations.length + 1;\r
+        }\r
 \r
-  public Vector getAAFrequency()\r
-  {\r
-    return AAFrequency.calculate(sequences, 0, getWidth());\r
-  }\r
-}\r
 \r
+        AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];\r
+        int i = 0;\r
 \r
+        if (aSize > 1)\r
+        {\r
+            for (i = 0; i < (aSize - 1); i++)\r
+            {\r
+                temp[i] = annotations[i];\r
+            }\r
+        }\r
 \r
+        temp[i] = aa;\r
 \r
+        annotations = temp;\r
+    }\r
 \r
+    /**\r
+     * DOCUMENT ME!\r
+     *\r
+     * @return DOCUMENT ME!\r
+     */\r
+    public AlignmentAnnotation[] getAlignmentAnnotation()\r
+    {\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
+\r
+          seqs[i] = new Sequence(getSequenceAt(i).getDisplayId(true),\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
+        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 void setProvenance(Provenance prov)\r
+    {\r
+      provenance = prov;\r
+    }\r
+    public Provenance getProvenance()\r
+    {\r
+      return provenance;\r
+    }\r
+}\r