2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 package jalview.datamodel;
23 import jalview.analysis.*;
25 /** Data structure to hold and manipulate a multiple sequence alignment
27 public class Alignment
30 protected Alignment dataset;
31 protected Vector sequences;
32 protected Vector groups = new Vector();
33 protected char gapCharacter = '-';
34 protected int type = NUCLEOTIDE;
35 public static final int PROTEIN = 0;
36 public static final int NUCLEOTIDE = 1;
39 public AlignmentAnnotation[] annotations;
41 HiddenSequences hiddenSequences = new HiddenSequences(this);
43 private void initAlignment(SequenceI[] seqs)
47 if (jalview.util.Comparison.isNucleotide(seqs))
56 sequences = new Vector();
58 for (i = 0; i < seqs.length; i++)
60 sequences.addElement(seqs[i]);
65 /** Make an alignment from an array of Sequences.
69 public Alignment(SequenceI[] seqs)
75 * Make a new alignment from an array of SeqCigars
76 * @param seqs SeqCigar[]
78 public Alignment(SeqCigar[] alseqs)
80 SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs, gapCharacter,
81 new ColumnSelection(), null);
86 * Make a new alignment from an CigarArray
87 * JBPNote - can only do this when compactAlignment does not contain hidden regions.
88 * JBPNote - must also check that compactAlignment resolves to a set of SeqCigars - or construct them appropriately.
89 * @param compactAlignment CigarArray
91 public static AlignmentI createAlignment(CigarArray compactAlignment)
93 throw new Error("Alignment(CigarArray) not yet implemented");
94 // this(compactAlignment.refCigars);
100 * @return DOCUMENT ME!
102 public Vector getSequences()
107 public SequenceI[] getSequencesArray()
109 SequenceI[] reply = new SequenceI[sequences.size()];
110 for (int i = 0; i < sequences.size(); i++)
112 reply[i] = (SequenceI) sequences.elementAt(i);
120 * @param i DOCUMENT ME!
122 * @return DOCUMENT ME!
124 public SequenceI getSequenceAt(int i)
126 if (i < sequences.size())
128 return (SequenceI) sequences.elementAt(i);
134 /** Adds a sequence to the alignment. Recalculates maxLength and size.
138 public void addSequence(SequenceI snew)
142 // maintain dataset integrity
143 if (snew.getDatasetSequence() != null)
145 getDataset().addSequence(snew.getDatasetSequence());
149 // derive new sequence
150 SequenceI adding = snew.deriveSequence();
151 getDataset().addSequence(adding.getDatasetSequence());
155 if (sequences==null) {
156 initAlignment(new SequenceI[] { snew });
158 sequences.addElement(snew);
160 if (hiddenSequences!=null)
161 hiddenSequences.adjustHeightSequenceAdded();
164 /** Adds a sequence to the alignment. Recalculates maxLength and size.
168 public void setSequenceAt(int i, SequenceI snew)
170 SequenceI oldseq = getSequenceAt(i);
171 deleteSequence(oldseq);
173 sequences.setElementAt(snew, i);
179 * @return DOCUMENT ME!
181 public Vector getGroups()
186 public void finalize()
188 if(getDataset()!=null)
189 getDataset().finalize();
195 hiddenSequences = null;
202 * @param s DOCUMENT ME!
204 public void deleteSequence(SequenceI s)
206 deleteSequence(findIndex(s));
212 * @param i DOCUMENT ME!
214 public void deleteSequence(int i)
216 if (i > -1 && i < getHeight())
218 sequences.removeElementAt(i);
219 hiddenSequences.adjustHeightSequenceDeleted(i);
224 public SequenceGroup findGroup(SequenceI s)
226 for (int i = 0; i < this.groups.size(); i++)
228 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
230 if (sg.getSequences(null).contains(s))
242 * @param s DOCUMENT ME!
244 * @return DOCUMENT ME!
246 public SequenceGroup[] findAllGroups(SequenceI s)
248 Vector temp = new Vector();
250 int gSize = groups.size();
251 for (int i = 0; i < gSize; i++)
253 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
254 if (sg == null || sg.getSequences(null) == null)
256 this.deleteGroup(sg);
261 if (sg.getSequences(null).contains(s))
267 SequenceGroup[] ret = new SequenceGroup[temp.size()];
269 for (int i = 0; i < temp.size(); i++)
271 ret[i] = (SequenceGroup) temp.elementAt(i);
278 public void addGroup(SequenceGroup sg)
280 if (!groups.contains(sg))
282 if (hiddenSequences.getSize() > 0)
284 int i, iSize = sg.getSize();
285 for (i = 0; i < iSize; i++)
287 if (!sequences.contains(sg.getSequenceAt(i)))
289 sg.deleteSequence(sg.getSequenceAt(i), false);
295 if (sg.getSize() < 1)
301 groups.addElement(sg);
308 public void deleteAllGroups()
310 groups.removeAllElements();
314 public void deleteGroup(SequenceGroup g)
316 if (groups.contains(g))
318 groups.removeElement(g);
323 public SequenceI findName(String name)
327 while (i < sequences.size())
329 if (getSequenceAt(i).getName().equals(name))
331 return getSequenceAt(i);
340 public SequenceI[] findSequenceMatch(String name)
342 Vector matches = new Vector();
345 while (i < sequences.size())
347 if (getSequenceAt(i).getName().equals(name))
349 matches.addElement(getSequenceAt(i));
354 SequenceI[] result = new SequenceI[matches.size()];
355 for (i = 0; i < result.length; i++)
357 result[i] = (SequenceI) matches.elementAt(i);
365 public int findIndex(SequenceI s)
369 while (i < sequences.size())
371 if (s == getSequenceAt(i))
385 * @return DOCUMENT ME!
387 public int getHeight()
389 return sequences.size();
395 * @return DOCUMENT ME!
397 public int getWidth()
401 for (int i = 0; i < sequences.size(); i++)
403 if (getSequenceAt(i).getLength() > maxLength)
405 maxLength = getSequenceAt(i).getLength();
415 * @param gc DOCUMENT ME!
417 public void setGapCharacter(char gc)
421 for (int i = 0; i < sequences.size(); i++)
423 Sequence seq = (Sequence) sequences.elementAt(i);
424 seq.setSequence(seq.getSequenceAsString()
435 * @return DOCUMENT ME!
437 public char getGapCharacter()
445 * @return DOCUMENT ME!
447 public boolean isAligned()
449 int width = getWidth();
451 for (int i = 0; i < sequences.size(); i++)
453 if (getSequenceAt(i).getLength() != width)
465 * @param aa DOCUMENT ME!
467 public void deleteAnnotation(AlignmentAnnotation aa)
471 if (annotations != null)
473 aSize = annotations.length;
481 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];
485 for (int i = 0; i < aSize; i++)
487 if (annotations[i] == aa)
492 temp[tIndex] = annotations[i];
502 * @param aa DOCUMENT ME!
504 public void addAnnotation(AlignmentAnnotation aa)
507 if (annotations != null)
509 aSize = annotations.length + 1;
512 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
514 temp[aSize - 1] = aa;
520 for (i = 0; i < (aSize - 1); i++)
522 temp[i] = annotations[i];
529 public void setAnnotationIndex(AlignmentAnnotation aa, int index)
531 if (aa == null || annotations == null || annotations.length - 1 < index)
536 int aSize = annotations.length;
537 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
541 for (int i = 0; i < aSize; i++)
550 temp[i] = annotations[i];
554 temp[i] = annotations[i - 1];
564 * @return DOCUMENT ME!
566 public AlignmentAnnotation[] getAlignmentAnnotation()
571 public void setNucleotide(boolean b)
583 public boolean isNucleotide()
585 if (type == NUCLEOTIDE)
595 public void setDataset(Alignment data)
597 if (dataset == null && data == null)
599 // Create a new dataset for this alignment.
600 // Can only be done once, if dataset is not null
601 // This will not be performed
602 Sequence[] seqs = new Sequence[getHeight()];
603 SequenceI currentSeq;
604 for (int i = 0; i < getHeight(); i++)
606 currentSeq = getSequenceAt(i);
607 if (currentSeq.getDatasetSequence() != null)
609 seqs[i] = (Sequence) currentSeq.getDatasetSequence();
613 seqs[i] = new Sequence(currentSeq.getName(),
614 AlignSeq.extractGaps(
615 jalview.util.Comparison.GapChars,
616 currentSeq.getSequenceAsString()
618 currentSeq.getStart(),
619 currentSeq.getEnd());
620 seqs[i].sequenceFeatures = currentSeq.getSequenceFeatures();
621 seqs[i].setDescription(currentSeq.getDescription());
622 getSequenceAt(i).setSequenceFeatures(null);
623 getSequenceAt(i).setDatasetSequence(seqs[i]);
627 dataset = new Alignment(seqs);
629 else if (dataset == null && data != null)
635 public Alignment getDataset()
640 public boolean padGaps()
642 boolean modified = false;
644 //Remove excess gaps from the end of alignment
648 for (int i = 0; i < sequences.size(); i++)
650 current = getSequenceAt(i);
651 for (int j = current.getLength(); j > maxLength; j--)
653 if (j > maxLength && !jalview.util.Comparison.isGap(
654 current.getCharAt(j)))
665 for (int i = 0; i < sequences.size();
668 current = getSequenceAt(i);
669 cLength = current.getLength();
671 if (cLength < maxLength)
673 current.insertCharAt(cLength,
674 maxLength - cLength, gapCharacter);
677 else if (current.getLength() > maxLength)
679 current.deleteChars(maxLength, current.getLength());
685 public HiddenSequences getHiddenSequences()
687 return hiddenSequences;
690 public CigarArray getCompactAlignment()
692 SeqCigar alseqs[] = new SeqCigar[sequences.size()];
693 for (int i = 0; i < sequences.size(); i++)
695 alseqs[i] = new SeqCigar( (SequenceI) sequences.elementAt(i));
697 CigarArray cal = new CigarArray(alseqs);
698 cal.addOperation(CigarArray.M, getWidth());