/* * Jalview - A Sequence Alignment Editor and Viewer * Copyright (C) 2005 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 * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package jalview.datamodel; import jalview.analysis.*; import jalview.util.*; import java.util.*; /** Data structure to hold and manipulate a multiple sequence alignment */ public class Alignment implements AlignmentI { protected Vector sequences; protected Vector groups = new Vector(); protected Vector superGroup = new Vector(); protected char gapCharacter = '-'; /** DOCUMENT ME!! */ public AlignmentAnnotation[] annotations; /** DOCUMENT ME!! */ public boolean featuresAdded = false; /** Make an alignment from an array of Sequences. * * @param sequences */ public Alignment(SequenceI[] seqs) { sequences = new Vector(); for (int i = 0; i < seqs.length; i++) { sequences.addElement(seqs[i]); } getWidth(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Vector getSequences() { return sequences; } /** * DOCUMENT ME! * * @param i DOCUMENT ME! * * @return DOCUMENT ME! */ public SequenceI getSequenceAt(int i) { if (i < sequences.size()) { return (SequenceI) sequences.elementAt(i); } return null; } /** Adds a sequence to the alignment. Recalculates maxLength and size. * * @param snew */ public void addSequence(SequenceI snew) { sequences.addElement(snew); } /** * DOCUMENT ME! * * @param seq DOCUMENT ME! */ public void addSequence(SequenceI[] seq) { for (int i = 0; i < seq.length; i++) { addSequence(seq[i]); } } /** Adds a sequence to the alignment. Recalculates maxLength and size. * * @param snew */ public void setSequenceAt(int i, SequenceI snew) { SequenceI oldseq = getSequenceAt(i); deleteSequence(oldseq); sequences.setElementAt(snew, i); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Vector getGroups() { return groups; } /** Takes out columns consisting entirely of gaps (-,.," ") */ public void removeGaps() { SequenceI current; int iSize = getWidth(); for (int i = 0; i < iSize; i++) { boolean delete = true; for (int j = 0; j < getHeight(); j++) { current = getSequenceAt(j); if (current.getLength() > i) { /* MC Should move this to a method somewhere */ if (!jalview.util.Comparison.isGap(current.getCharAt(i))) { delete = false; } } } if (delete) { deleteColumns(i, i); iSize--; i--; } } } /** Removes a range of columns (start to end inclusive). * * @param start Start column in the alignment * @param end End column in the alignment */ public void deleteColumns(int start, int end) { deleteColumns(0, getHeight() - 1, start, end); } /** * DOCUMENT ME! * * @param seq1 DOCUMENT ME! * @param seq2 DOCUMENT ME! * @param start DOCUMENT ME! * @param end DOCUMENT ME! */ public void deleteColumns(int seq1, int seq2, int start, int end) { for (int i = 0; i <= (end - start); i++) { for (int j = seq1; j <= seq2; j++) { getSequenceAt(j).deleteCharAt(start); } } } /** * DOCUMENT ME! * * @param i DOCUMENT ME! */ public void trimLeft(int i) { for (int j = 0; j < getHeight(); j++) { SequenceI s = getSequenceAt(j); int newstart = s.findPosition(i); s.setStart(newstart); s.setSequence(s.getSequence().substring(i)); } } /** * DOCUMENT ME! * * @param i DOCUMENT ME! */ public void trimRight(int i) { for (int j = 0; j < getHeight(); j++) { SequenceI s = getSequenceAt(j); int newend = s.findPosition(i); s.setEnd(newend); s.setSequence(s.getSequence().substring(0, i + 1)); } } /** * DOCUMENT ME! * * @param s DOCUMENT ME! */ public void deleteSequence(SequenceI s) { for (int i = 0; i < getHeight(); i++) { if (getSequenceAt(i) == s) { deleteSequence(i); } } } /** * DOCUMENT ME! * * @param i DOCUMENT ME! */ public void deleteSequence(int i) { sequences.removeElementAt(i); } /** * DOCUMENT ME! * * @param threshold DOCUMENT ME! * @param sel DOCUMENT ME! * * @return DOCUMENT ME! */ public Vector removeRedundancy(float threshold, Vector sel) { Vector del = new Vector(); for (int i = 1; i < sel.size(); i++) { for (int j = 0; j < i; j++) { // Only do the comparison if either have not been deleted if (!del.contains((SequenceI) sel.elementAt(i)) || !del.contains((SequenceI) sel.elementAt(j))) { // use PID instead of Comparison (which is really not pleasant) float pid = Comparison.PID((SequenceI) sel.elementAt(j), (SequenceI) sel.elementAt(i)); if (pid >= threshold) { // Delete the shortest one if (((SequenceI) sel.elementAt(j)).getSequence().length() > ((SequenceI) sel .elementAt( i)).getSequence().length()) { del.addElement(sel.elementAt(i)); } else { del.addElement(sel.elementAt(i)); } } } } } // Now delete the sequences for (int i = 0; i < del.size(); i++) { deleteSequence((SequenceI) del.elementAt(i)); } return del; } /** */ public SequenceGroup findGroup(int i) { return findGroup(getSequenceAt(i)); } /** */ public SequenceGroup findGroup(SequenceI s) { for (int i = 0; i < this.groups.size(); i++) { SequenceGroup sg = (SequenceGroup) groups.elementAt(i); if (sg.sequences.contains(s)) { return sg; } } return null; } /** * DOCUMENT ME! * * @param s DOCUMENT ME! * * @return DOCUMENT ME! */ public SequenceGroup[] findAllGroups(SequenceI s) { Vector temp = new Vector(); for (int i = 0; i < this.groups.size(); i++) { SequenceGroup sg = (SequenceGroup) groups.elementAt(i); if (sg.sequences.contains(s)) { temp.addElement(sg); } } SequenceGroup[] ret = new SequenceGroup[temp.size()]; for (int i = 0; i < temp.size(); i++) { ret[i] = (SequenceGroup) temp.elementAt(i); } return ret; } /** * DOCUMENT ME! * * @param sg DOCUMENT ME! */ public void addSuperGroup(SuperGroup sg) { superGroup.addElement(sg); } /** * DOCUMENT ME! * * @param sg DOCUMENT ME! */ public void removeSuperGroup(SuperGroup sg) { superGroup.removeElement(sg); } /** * DOCUMENT ME! * * @param sg DOCUMENT ME! * * @return DOCUMENT ME! */ public SuperGroup getSuperGroup(SequenceGroup sg) { for (int i = 0; i < this.superGroup.size(); i++) { SuperGroup temp = (SuperGroup) superGroup.elementAt(i); if (temp.sequenceGroups.contains(sg)) { return temp; } } return null; } /** */ public void addGroup(SequenceGroup sg) { if (!groups.contains(sg)) { groups.addElement(sg); } } /** * DOCUMENT ME! */ public void deleteAllGroups() { groups.removeAllElements(); superGroup.removeAllElements(); int i = 0; while (i < sequences.size()) { SequenceI s = getSequenceAt(i); s.setColor(java.awt.Color.white); i++; } } /** */ public void deleteGroup(SequenceGroup g) { if (groups.contains(g)) { groups.removeElement(g); } } /** */ public SequenceI findName(String name) { int i = 0; while (i < sequences.size()) { SequenceI s = getSequenceAt(i); if (s.getName().equals(name)) { return s; } i++; } return null; } /** */ public SequenceI findbyDisplayId(String name) { int i = 0; while (i < sequences.size()) { SequenceI s = getSequenceAt(i); if (s.getDisplayId().equals(name)) { return s; } i++; } return null; } /** */ public int findIndex(SequenceI s) { int i = 0; while (i < sequences.size()) { if (s == getSequenceAt(i)) { return i; } i++; } return -1; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public int getHeight() { return sequences.size(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public int getWidth() { int maxLength = -1; for (int i = 0; i < sequences.size(); i++) { if (getSequenceAt(i).getLength() > maxLength) { maxLength = getSequenceAt(i).getLength(); } } return maxLength; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public int getMaxIdLength() { int max = 0; int i = 0; while (i < sequences.size()) { SequenceI seq = getSequenceAt(i); String tmp = seq.getName() + "/" + seq.getStart() + "-" + seq.getEnd(); if (tmp.length() > max) { max = tmp.length(); } i++; } return max; } /** * DOCUMENT ME! * * @param gc DOCUMENT ME! */ public void setGapCharacter(char gc) { gapCharacter = gc; for (int i = 0; i < sequences.size(); i++) { Sequence seq = (Sequence) sequences.elementAt(i); seq.sequence = seq.sequence.replace('.', gc); seq.sequence = seq.sequence.replace('-', gc); seq.sequence = seq.sequence.replace(' ', gc); } } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public char getGapCharacter() { return gapCharacter; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public Vector getAAFrequency() { return AAFrequency.calculate(sequences, 0, getWidth()); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean isAligned() { int width = getWidth(); for (int i = 0; i < sequences.size(); i++) { if (getSequenceAt(i).getLength() != width) { return false; } } return true; } /** * DOCUMENT ME! * * @param aa DOCUMENT ME! */ public void deleteAnnotation(AlignmentAnnotation aa) { int aSize = 1; if (annotations != null) { aSize = annotations.length; } AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1]; int tIndex = 0; for (int i = 0; i < aSize; i++) { if (annotations[i] == aa) { continue; } temp[tIndex] = annotations[i]; tIndex++; } annotations = temp; } /** * DOCUMENT ME! * * @param aa DOCUMENT ME! */ public void addAnnotation(AlignmentAnnotation aa) { int aSize = 1; if (annotations != null) { aSize = annotations.length + 1; } AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize]; int i = 0; if (aSize > 1) { for (i = 0; i < (aSize - 1); i++) { temp[i] = annotations[i]; } } temp[i] = aa; annotations = temp; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public AlignmentAnnotation[] getAlignmentAnnotation() { return annotations; } }