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.*;
25 /** Data structure to hold and manipulate a multiple sequence alignment
27 public class Alignment implements AlignmentI
29 protected Alignment dataset;
30 protected Vector sequences;
31 protected Vector groups = new Vector();
32 protected char gapCharacter = '-';
33 protected int type = NUCLEOTIDE;
34 public static final int PROTEIN = 0;
35 public static final int NUCLEOTIDE = 1;
38 public AlignmentAnnotation[] annotations;
40 HiddenSequences hiddenSequences = new HiddenSequences(this);
42 private void initAlignment(SequenceI[] seqs) {
45 if( jalview.util.Comparison.isNucleotide(seqs))
50 sequences = new Vector();
52 for (i = 0; i < seqs.length; i++)
54 sequences.addElement(seqs[i]);
58 /** Make an alignment from an array of Sequences.
62 public Alignment(SequenceI[] seqs)
67 * Make a new alignment from an array of SeqCigars
68 * @param seqs SeqCigar[]
70 public Alignment(SeqCigar[] alseqs) {
71 SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs, gapCharacter, new ColumnSelection(), null);
75 * Make a new alignment from an CigarArray
76 * JBPNote - can only do this when compactAlignment does not contain hidden regions.
77 * JBPNote - must also check that compactAlignment resolves to a set of SeqCigars - or construct them appropriately.
78 * @param compactAlignment CigarArray
80 public static AlignmentI createAlignment(CigarArray compactAlignment) {
81 throw new Error("Alignment(CigarArray) not yet implemented");
82 // this(compactAlignment.refCigars);
88 * @return DOCUMENT ME!
90 public Vector getSequences()
95 public SequenceI [] getSequencesArray()
97 SequenceI [] reply = new SequenceI[sequences.size()];
98 for(int i=0; i<sequences.size(); i++)
100 reply[i] = (SequenceI)sequences.elementAt(i);
108 * @param i DOCUMENT ME!
110 * @return DOCUMENT ME!
112 public SequenceI getSequenceAt(int i)
114 if (i < sequences.size())
116 return (SequenceI) sequences.elementAt(i);
122 /** Adds a sequence to the alignment. Recalculates maxLength and size.
126 public void addSequence(SequenceI snew)
130 if(snew.getDatasetSequence()!=null)
132 getDataset().addSequence(snew.getDatasetSequence());
136 Sequence ds = new Sequence(snew.getName(),
137 AlignSeq.extractGaps("-. ",
138 snew.getSequenceAsString()),
142 snew.setDatasetSequence(ds);
143 getDataset().addSequence(ds);
146 sequences.addElement(snew);
148 hiddenSequences.adjustHeightSequenceAdded();
152 /** Adds a sequence to the alignment. Recalculates maxLength and size.
156 public void setSequenceAt(int i, SequenceI snew)
158 SequenceI oldseq = getSequenceAt(i);
159 deleteSequence(oldseq);
161 sequences.setElementAt(snew, i);
167 * @return DOCUMENT ME!
169 public Vector getGroups()
177 * @param s DOCUMENT ME!
179 public void deleteSequence(SequenceI s)
181 deleteSequence(findIndex(s));
187 * @param i DOCUMENT ME!
189 public void deleteSequence(int i)
191 if(i>-1 && i<getHeight())
193 sequences.removeElementAt(i);
194 hiddenSequences.adjustHeightSequenceDeleted(i);
200 public SequenceGroup findGroup(SequenceI s)
202 for (int i = 0; i < this.groups.size(); i++)
204 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
206 if (sg.getSequences(false).contains(s))
218 * @param s DOCUMENT ME!
220 * @return DOCUMENT ME!
222 public SequenceGroup[] findAllGroups(SequenceI s)
224 Vector temp = new Vector();
226 int gSize = groups.size();
227 for (int i = 0; i < gSize; i++)
229 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
230 if(sg==null || sg.getSequences(false)==null)
232 this.deleteGroup(sg);
237 if (sg.getSequences(false).contains(s))
243 SequenceGroup[] ret = new SequenceGroup[temp.size()];
245 for (int i = 0; i < temp.size(); i++)
247 ret[i] = (SequenceGroup) temp.elementAt(i);
256 public void addGroup(SequenceGroup sg)
258 if (!groups.contains(sg))
260 if(hiddenSequences.getSize()>0)
262 //We're not going to make groups of
264 int i, iSize = sg.getSize(false);
265 for (i = 0; i < iSize; i++)
267 if (!sequences.contains(sg.getSequenceAt(i)))
269 sg.deleteSequence(sg.getSequenceAt(i), false);
275 if (sg.getSize(true) < 1)
279 groups.addElement(sg);
286 public void deleteAllGroups()
288 groups.removeAllElements();
292 public void deleteGroup(SequenceGroup g)
294 if (groups.contains(g))
296 groups.removeElement(g);
301 public SequenceI findName(String name)
305 while (i < sequences.size())
307 if (getSequenceAt(i).getName().equals(name))
309 return getSequenceAt(i);
318 public SequenceI [] findSequenceMatch(String name)
320 Vector matches = new Vector();
323 while (i < sequences.size())
325 if (getSequenceAt(i).getName().equals(name))
327 matches.addElement(getSequenceAt(i));
332 SequenceI [] result = new SequenceI[matches.size()];
333 for(i=0; i<result.length; i++)
334 result[i] = (SequenceI)matches.elementAt(i);
342 public int findIndex(SequenceI s)
346 while (i < sequences.size())
348 if (s == getSequenceAt(i))
362 * @return DOCUMENT ME!
364 public int getHeight()
366 return sequences.size();
372 * @return DOCUMENT ME!
374 public int getWidth()
378 for (int i = 0; i < sequences.size(); i++)
380 if (getSequenceAt(i).getLength() > maxLength)
382 maxLength = getSequenceAt(i).getLength();
393 * @param gc DOCUMENT ME!
395 public void setGapCharacter(char gc)
399 for (int i = 0; i < sequences.size(); i++)
401 Sequence seq = (Sequence) sequences.elementAt(i);
402 seq.setSequence( seq.getSequenceAsString().replace('.', gc) );
403 seq.setSequence( seq.getSequenceAsString().replace('-', gc) );
404 seq.setSequence( seq.getSequenceAsString().replace(' ', gc) );
411 * @return DOCUMENT ME!
413 public char getGapCharacter()
422 * @return DOCUMENT ME!
424 public boolean isAligned()
426 int width = getWidth();
428 for (int i = 0; i < sequences.size(); i++)
430 if (getSequenceAt(i).getLength() != width)
442 * @param aa DOCUMENT ME!
444 public void deleteAnnotation(AlignmentAnnotation aa)
448 if (annotations != null)
450 aSize = annotations.length;
456 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];
460 for (int i = 0; i < aSize; i++)
462 if (annotations[i] == aa)
467 temp[tIndex] = annotations[i];
475 public void adjustSequenceAnnotations()
477 if(annotations!=null)
479 for (int a = 0; a < annotations.length; a++)
481 if (annotations[a].sequenceRef != null)
483 annotations[a].adjustForAlignment();
492 * @param aa DOCUMENT ME!
494 public void addAnnotation(AlignmentAnnotation aa)
497 if (annotations != null)
499 aSize = annotations.length + 1;
502 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
510 for (i = 0; i < (aSize-1); i++)
512 temp[i] = annotations[i];
519 public void setAnnotationIndex(AlignmentAnnotation aa, int index)
521 if(aa==null || annotations==null || annotations.length-1<index)
524 int aSize = annotations.length;
525 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
529 for (int i = 0; i < aSize; i++)
535 temp[i] = annotations[i];
537 temp[i] = annotations[i-1];
546 * @return DOCUMENT ME!
548 public AlignmentAnnotation[] getAlignmentAnnotation()
553 public void setNucleotide(boolean b)
561 public boolean isNucleotide()
569 public void setDataset(Alignment data)
571 if(dataset==null && data==null)
573 // Create a new dataset for this alignment.
574 // Can only be done once, if dataset is not null
575 // This will not be performed
576 Sequence[] seqs = new Sequence[getHeight()];
577 SequenceI currentSeq;
578 for (int i = 0; i < getHeight(); i++)
580 currentSeq = getSequenceAt(i);
581 if(currentSeq.getDatasetSequence()!=null)
583 seqs[i] = (Sequence)currentSeq.getDatasetSequence();
587 seqs[i] = new Sequence(currentSeq.getName(),
588 AlignSeq.extractGaps(
589 jalview.util.Comparison.GapChars,
590 currentSeq.getSequenceAsString()
592 currentSeq.getStart(),
593 currentSeq.getEnd());
594 seqs[i].sequenceFeatures = currentSeq.getSequenceFeatures();
595 seqs[i].setDescription(currentSeq.getDescription());
596 getSequenceAt(i).setSequenceFeatures(null);
597 getSequenceAt(i).setDatasetSequence(seqs[i]);
601 dataset = new Alignment(seqs);
603 else if(dataset==null && data!=null)
609 public Alignment getDataset()
614 public boolean padGaps()
616 boolean modified=false;
618 //Remove excess gaps from the end of alignment
622 for (int i = 0; i < sequences.size(); i++)
624 current = getSequenceAt(i);
625 for (int j = current.getLength(); j > maxLength; j--)
627 if (j > maxLength && !jalview.util.Comparison.isGap(
628 current.getCharAt(j)))
639 for (int i = 0; i < sequences.size();
642 current = getSequenceAt(i);
643 cLength = current.getLength();
645 if (cLength < maxLength)
647 current.insertCharAt(cLength,
648 maxLength-cLength, gapCharacter);
651 else if(current.getLength() > maxLength)
653 current.deleteChars(maxLength, current.getLength());
659 public HiddenSequences getHiddenSequences()
661 return hiddenSequences;
663 SequenceI [] getVisibleAndRepresentedSeqs()
665 if(hiddenSequences==null || hiddenSequences.getSize()<1)
666 return getSequencesArray();
668 Vector seqs = new Vector();
670 SequenceGroup hidden;
671 for (int i = 0; i < sequences.size(); i++)
673 seq = (SequenceI) sequences.elementAt(i);
674 seqs.addElement(seq);
675 hidden = seq.getHiddenSequences();
678 for(int j=0; j<hidden.getSize(false); j++)
680 seqs.addElement(hidden.getSequenceAt(j));
684 SequenceI [] result = new SequenceI[seqs.size()];
685 for(int i=0; i<seqs.size(); i++)
686 result[i] = (SequenceI)seqs.elementAt(i);
692 public CigarArray getCompactAlignment()
694 SeqCigar alseqs[] = new SeqCigar[sequences.size()];
695 for (int i=0; i<sequences.size(); i++) {
696 alseqs[i] = new SeqCigar((SequenceI) sequences.elementAt(i));
698 CigarArray cal = new CigarArray(alseqs);
699 cal.addOperation(CigarArray.M, getWidth());