2 * Jalview - A Sequence Alignment Editor and Viewer
3 * Copyright (C) 2006 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;
21 import jalview.analysis.*;
23 import jalview.util.*;
27 /** Data structure to hold and manipulate a multiple sequence alignment
29 public class Alignment implements AlignmentI
31 protected Alignment dataset;
32 protected Vector sequences;
33 protected Vector groups = new Vector();
34 protected char gapCharacter = '-';
35 protected int type = NUCLEOTIDE;
36 public static final int PROTEIN = 0;
37 public static final int NUCLEOTIDE = 1;
40 public AlignmentAnnotation[] annotations;
42 HiddenSequences hiddenSequences = new HiddenSequences(this);
44 private void initAlignment(SequenceI[] seqs) {
47 if( jalview.util.Comparison.isNucleotide(seqs))
52 sequences = new Vector();
54 for (i = 0; i < seqs.length; i++)
56 sequences.addElement(seqs[i]);
60 /** Make an alignment from an array of Sequences.
64 public Alignment(SequenceI[] seqs)
69 * Make a new alignment from an array of SeqCigars
70 * @param seqs SeqCigar[]
72 public Alignment(SeqCigar[] alseqs) {
73 SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs, gapCharacter, new ColumnSelection(), null);
77 * Make a new alignment from an CigarArray
78 * JBPNote - can only do this when compactAlignment does not contain hidden regions.
79 * JBPNote - must also check that compactAlignment resolves to a set of SeqCigars - or construct them appropriately.
80 * @param compactAlignment CigarArray
82 public static AlignmentI createAlignment(CigarArray compactAlignment) {
83 throw new Error("Alignment(CigarArray) not yet implemented");
84 // this(compactAlignment.refCigars);
90 * @return DOCUMENT ME!
92 public Vector getSequences()
97 public SequenceI [] getSequencesArray()
99 SequenceI [] reply = new SequenceI[sequences.size()];
100 for(int i=0; i<sequences.size(); i++)
102 reply[i] = (SequenceI)sequences.elementAt(i);
110 * @param i DOCUMENT ME!
112 * @return DOCUMENT ME!
114 public SequenceI getSequenceAt(int i)
116 if (i < sequences.size())
118 return (SequenceI) sequences.elementAt(i);
124 /** Adds a sequence to the alignment. Recalculates maxLength and size.
128 public void addSequence(SequenceI snew)
132 if(snew.getDatasetSequence()!=null)
134 getDataset().addSequence(snew.getDatasetSequence());
138 Sequence ds = new Sequence(snew.getName(),
139 AlignSeq.extractGaps("-. ",
144 snew.setDatasetSequence(ds);
145 getDataset().addSequence(ds);
148 sequences.addElement(snew);
150 hiddenSequences.adjustHeightSequenceAdded();
154 /** Adds a sequence to the alignment. Recalculates maxLength and size.
158 public void setSequenceAt(int i, SequenceI snew)
160 SequenceI oldseq = getSequenceAt(i);
161 deleteSequence(oldseq);
163 sequences.setElementAt(snew, i);
169 * @return DOCUMENT ME!
171 public Vector getGroups()
179 * @param s DOCUMENT ME!
181 public void deleteSequence(SequenceI s)
183 deleteSequence(findIndex(s));
189 * @param i DOCUMENT ME!
191 public void deleteSequence(int i)
193 if(i>-1 && i<getHeight())
195 sequences.removeElementAt(i);
196 hiddenSequences.adjustHeightSequenceDeleted(i);
202 public SequenceGroup findGroup(SequenceI s)
204 for (int i = 0; i < this.groups.size(); i++)
206 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
208 if (sg.getSequences(false).contains(s))
220 * @param s DOCUMENT ME!
222 * @return DOCUMENT ME!
224 public SequenceGroup[] findAllGroups(SequenceI s)
226 Vector temp = new Vector();
228 int gSize = groups.size();
229 for (int i = 0; i < gSize; i++)
231 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
232 if(sg==null || sg.getSequences(false)==null)
234 this.deleteGroup(sg);
239 if (sg.getSequences(false).contains(s))
245 SequenceGroup[] ret = new SequenceGroup[temp.size()];
247 for (int i = 0; i < temp.size(); i++)
249 ret[i] = (SequenceGroup) temp.elementAt(i);
258 public void addGroup(SequenceGroup sg)
260 if (!groups.contains(sg))
262 if(hiddenSequences.getSize()>0)
264 //We're not going to make groups of
266 int i, iSize = sg.getSize(false);
267 for (i = 0; i < iSize; i++)
269 if (!sequences.contains(sg.getSequenceAt(i)))
271 sg.deleteSequence(sg.getSequenceAt(i), false);
277 if (sg.getSize(true) < 1)
281 groups.addElement(sg);
288 public void deleteAllGroups()
290 groups.removeAllElements();
294 public void deleteGroup(SequenceGroup g)
296 if (groups.contains(g))
298 groups.removeElement(g);
303 public SequenceI findName(String name)
307 while (i < sequences.size())
309 if (getSequenceAt(i).getName().equals(name))
311 return getSequenceAt(i);
320 public SequenceI [] findSequenceMatch(String name)
322 Vector matches = new Vector();
325 while (i < sequences.size())
327 if (getSequenceAt(i).getName().equals(name))
329 matches.addElement(getSequenceAt(i));
334 SequenceI [] result = new SequenceI[matches.size()];
335 for(i=0; i<result.length; i++)
336 result[i] = (SequenceI)matches.elementAt(i);
344 public int findIndex(SequenceI s)
348 while (i < sequences.size())
350 if (s == getSequenceAt(i))
364 * @return DOCUMENT ME!
366 public int getHeight()
368 return sequences.size();
374 * @return DOCUMENT ME!
376 public int getWidth()
380 for (int i = 0; i < sequences.size(); i++)
382 if (getSequenceAt(i).getLength() > maxLength)
384 maxLength = getSequenceAt(i).getLength();
395 * @param gc DOCUMENT ME!
397 public void setGapCharacter(char gc)
401 for (int i = 0; i < sequences.size(); i++)
403 Sequence seq = (Sequence) sequences.elementAt(i);
404 seq.setSequence( seq.getSequence().replace('.', gc) );
405 seq.setSequence( seq.getSequence().replace('-', gc) );
406 seq.setSequence( seq.getSequence().replace(' ', gc) );
413 * @return DOCUMENT ME!
415 public char getGapCharacter()
424 * @return DOCUMENT ME!
426 public boolean isAligned()
428 int width = getWidth();
430 for (int i = 0; i < sequences.size(); i++)
432 if (getSequenceAt(i).getLength() != width)
444 * @param aa DOCUMENT ME!
446 public void deleteAnnotation(AlignmentAnnotation aa)
450 if (annotations != null)
452 aSize = annotations.length;
458 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];
462 for (int i = 0; i < aSize; i++)
464 if (annotations[i] == aa)
469 temp[tIndex] = annotations[i];
477 public void adjustSequenceAnnotations()
479 if(annotations!=null)
481 for (int a = 0; a < annotations.length; a++)
483 if (annotations[a].sequenceRef != null)
485 annotations[a].adjustForAlignment();
494 * @param aa DOCUMENT ME!
496 public void addAnnotation(AlignmentAnnotation aa)
499 if (annotations != null)
501 aSize = annotations.length + 1;
504 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
512 for (i = 0; i < (aSize-1); i++)
514 temp[i] = annotations[i];
521 public void setAnnotationIndex(AlignmentAnnotation aa, int index)
523 if(aa==null || annotations==null || annotations.length-1<index)
526 int aSize = annotations.length;
527 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
531 for (int i = 0; i < aSize; i++)
537 temp[i] = annotations[i];
539 temp[i] = annotations[i-1];
548 * @return DOCUMENT ME!
550 public AlignmentAnnotation[] getAlignmentAnnotation()
555 public void setNucleotide(boolean b)
563 public boolean isNucleotide()
571 public void setDataset(Alignment data)
573 if(dataset==null && data==null)
575 // Create a new dataset for this alignment.
576 // Can only be done once, if dataset is not null
577 // This will not be performed
578 Sequence[] seqs = new Sequence[getHeight()];
579 SequenceI currentSeq;
580 for (int i = 0; i < getHeight(); i++)
582 currentSeq = getSequenceAt(i);
583 if(currentSeq.getDatasetSequence()!=null)
585 seqs[i] = (Sequence)currentSeq.getDatasetSequence();
589 seqs[i] = new Sequence(currentSeq.getName(),
590 AlignSeq.extractGaps(
591 jalview.util.Comparison.GapChars,
592 currentSeq.getSequence()
594 currentSeq.getStart(),
595 currentSeq.getEnd());
596 seqs[i].sequenceFeatures = currentSeq.getSequenceFeatures();
597 seqs[i].setDescription(currentSeq.getDescription());
598 getSequenceAt(i).setSequenceFeatures(null);
599 getSequenceAt(i).setDatasetSequence(seqs[i]);
603 dataset = new Alignment(seqs);
605 else if(dataset==null && data!=null)
611 public Alignment getDataset()
616 public boolean padGaps()
618 boolean modified=false;
620 //Remove excess gaps from the end of alignment
624 for (int i = 0; i < sequences.size(); i++)
626 current = getSequenceAt(i);
627 for (int j = current.getLength(); j > maxLength; j--)
629 if (j > maxLength && !jalview.util.Comparison.isGap(
630 current.getCharAt(j)))
641 for (int i = 0; i < sequences.size();
644 current = getSequenceAt(i);
645 cLength = current.getLength();
647 if (cLength < maxLength)
649 current.insertCharAt(cLength,
650 maxLength-cLength, gapCharacter);
653 else if(current.getLength() > maxLength)
655 current.deleteChars(maxLength, current.getLength());
661 public HiddenSequences getHiddenSequences()
663 return hiddenSequences;
665 SequenceI [] getVisibleAndRepresentedSeqs()
667 if(hiddenSequences==null || hiddenSequences.getSize()<1)
668 return getSequencesArray();
670 Vector seqs = new Vector();
672 SequenceGroup hidden;
673 for (int i = 0; i < sequences.size(); i++)
675 seq = (SequenceI) sequences.elementAt(i);
676 seqs.addElement(seq);
677 hidden = seq.getHiddenSequences();
680 for(int j=0; j<hidden.getSize(false); j++)
682 seqs.addElement(hidden.getSequenceAt(j));
686 SequenceI [] result = new SequenceI[seqs.size()];
687 for(int i=0; i<seqs.size(); i++)
688 result[i] = (SequenceI)seqs.elementAt(i);
694 public CigarArray getCompactAlignment()
696 SeqCigar alseqs[] = new SeqCigar[sequences.size()];
697 for (int i=0; i<sequences.size(); i++) {
698 alseqs[i] = new SeqCigar((SequenceI) sequences.elementAt(i));
700 CigarArray cal = new CigarArray(alseqs);
701 cal.addOperation(CigarArray.M, getWidth());