2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3 * Copyright (C) 2008 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 public Hashtable alignmentProperties;
45 private void initAlignment(SequenceI[] seqs)
49 if (jalview.util.Comparison.isNucleotide(seqs))
58 sequences = new Vector();
60 for (i = 0; i < seqs.length; i++)
62 sequences.addElement(seqs[i]);
67 /** Make an alignment from an array of Sequences.
71 public Alignment(SequenceI[] seqs)
77 * Make a new alignment from an array of SeqCigars
78 * @param seqs SeqCigar[]
80 public Alignment(SeqCigar[] alseqs)
82 SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs, gapCharacter,
83 new ColumnSelection(), null);
88 * Make a new alignment from an CigarArray
89 * JBPNote - can only do this when compactAlignment does not contain hidden regions.
90 * JBPNote - must also check that compactAlignment resolves to a set of SeqCigars - or construct them appropriately.
91 * @param compactAlignment CigarArray
93 public static AlignmentI createAlignment(CigarArray compactAlignment)
95 throw new Error("Alignment(CigarArray) not yet implemented");
96 // this(compactAlignment.refCigars);
102 * @return DOCUMENT ME!
104 public Vector getSequences()
109 public SequenceI[] getSequencesArray()
113 SequenceI[] reply = new SequenceI[sequences.size()];
114 for (int i = 0; i < sequences.size(); i++)
116 reply[i] = (SequenceI) sequences.elementAt(i);
124 * @param i DOCUMENT ME!
126 * @return DOCUMENT ME!
128 public SequenceI getSequenceAt(int i)
130 if (i < sequences.size())
132 return (SequenceI) sequences.elementAt(i);
138 /** Adds a sequence to the alignment. Recalculates maxLength and size.
142 public void addSequence(SequenceI snew)
146 // maintain dataset integrity
147 if (snew.getDatasetSequence() != null)
149 getDataset().addSequence(snew.getDatasetSequence());
153 // derive new sequence
154 SequenceI adding = snew.deriveSequence();
155 getDataset().addSequence(adding.getDatasetSequence());
159 if (sequences==null) {
160 initAlignment(new SequenceI[] { snew });
162 sequences.addElement(snew);
164 if (hiddenSequences!=null)
165 hiddenSequences.adjustHeightSequenceAdded();
168 /** Adds a sequence to the alignment. Recalculates maxLength and size.
172 public void setSequenceAt(int i, SequenceI snew)
174 SequenceI oldseq = getSequenceAt(i);
175 deleteSequence(oldseq);
177 sequences.setElementAt(snew, i);
183 * @return DOCUMENT ME!
185 public Vector getGroups()
190 public void finalize()
192 if(getDataset()!=null)
193 getDataset().removeAlignmentRef();
199 hiddenSequences = null;
203 * decrement the alignmentRefs counter by one and call finalize if it goes to zero.
205 private void removeAlignmentRef()
207 if (--alignmentRefs==0)
216 * @param s DOCUMENT ME!
218 public void deleteSequence(SequenceI s)
220 deleteSequence(findIndex(s));
226 * @param i DOCUMENT ME!
228 public void deleteSequence(int i)
230 if (i > -1 && i < getHeight())
232 sequences.removeElementAt(i);
233 hiddenSequences.adjustHeightSequenceDeleted(i);
238 public SequenceGroup findGroup(SequenceI s)
240 for (int i = 0; i < this.groups.size(); i++)
242 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
244 if (sg.getSequences(null).contains(s))
256 * @param s DOCUMENT ME!
258 * @return DOCUMENT ME!
260 public SequenceGroup[] findAllGroups(SequenceI s)
262 Vector temp = new Vector();
264 int gSize = groups.size();
265 for (int i = 0; i < gSize; i++)
267 SequenceGroup sg = (SequenceGroup) groups.elementAt(i);
268 if (sg == null || sg.getSequences(null) == null)
270 this.deleteGroup(sg);
275 if (sg.getSequences(null).contains(s))
281 SequenceGroup[] ret = new SequenceGroup[temp.size()];
283 for (int i = 0; i < temp.size(); i++)
285 ret[i] = (SequenceGroup) temp.elementAt(i);
292 public void addGroup(SequenceGroup sg)
294 if (!groups.contains(sg))
296 if (hiddenSequences.getSize() > 0)
298 int i, iSize = sg.getSize();
299 for (i = 0; i < iSize; i++)
301 if (!sequences.contains(sg.getSequenceAt(i)))
303 sg.deleteSequence(sg.getSequenceAt(i), false);
309 if (sg.getSize() < 1)
315 groups.addElement(sg);
322 public void deleteAllGroups()
324 groups.removeAllElements();
328 public void deleteGroup(SequenceGroup g)
330 if (groups.contains(g))
332 groups.removeElement(g);
337 public SequenceI findName(String name)
339 return findName(name,false);
343 * @see jalview.datamodel.AlignmentI#findName(java.lang.String, boolean)
345 public SequenceI findName(String token, boolean b)
347 return findName(null, token, b);
351 * @see jalview.datamodel.AlignmentI#findName(SequenceI, java.lang.String, boolean)
353 public SequenceI findName(SequenceI startAfter, String token, boolean b)
359 if (startAfter!=null)
361 // try to find the sequence in the alignment
362 boolean matched=false;
363 while (i<sequences.size())
365 if (getSequenceAt(i++)==startAfter)
376 while (i < sequences.size())
378 sq = getSequenceAt(i);
379 sqname = sq.getName();
380 if (sqname.equals(token) // exact match
381 || (b && // allow imperfect matches - case varies
382 (sqname.equalsIgnoreCase(token))))
384 return getSequenceAt(i);
392 public SequenceI[] findSequenceMatch(String name)
394 Vector matches = new Vector();
397 while (i < sequences.size())
399 if (getSequenceAt(i).getName().equals(name))
401 matches.addElement(getSequenceAt(i));
406 SequenceI[] result = new SequenceI[matches.size()];
407 for (i = 0; i < result.length; i++)
409 result[i] = (SequenceI) matches.elementAt(i);
417 public int findIndex(SequenceI s)
421 while (i < sequences.size())
423 if (s == getSequenceAt(i))
437 * @return DOCUMENT ME!
439 public int getHeight()
441 return sequences.size();
447 * @return DOCUMENT ME!
449 public int getWidth()
453 for (int i = 0; i < sequences.size(); i++)
455 if (getSequenceAt(i).getLength() > maxLength)
457 maxLength = getSequenceAt(i).getLength();
467 * @param gc DOCUMENT ME!
469 public void setGapCharacter(char gc)
473 for (int i = 0; i < sequences.size(); i++)
475 Sequence seq = (Sequence) sequences.elementAt(i);
476 seq.setSequence(seq.getSequenceAsString()
487 * @return DOCUMENT ME!
489 public char getGapCharacter()
497 * @return DOCUMENT ME!
499 public boolean isAligned()
501 int width = getWidth();
503 for (int i = 0; i < sequences.size(); i++)
505 if (getSequenceAt(i).getLength() != width)
514 * @see jalview.datamodel.AlignmentI#deleteAnnotation(jalview.datamodel.AlignmentAnnotation)
516 public boolean deleteAnnotation(AlignmentAnnotation aa)
520 if (annotations != null)
522 aSize = annotations.length;
530 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];
535 for (int i = 0; i < aSize; i++)
537 if (annotations[i] == aa)
542 if (tIndex<temp.length)
543 temp[tIndex++] = annotations[i];
549 if(aa.sequenceRef!=null)
550 aa.sequenceRef.removeAlignmentAnnotation(aa);
558 * @param aa DOCUMENT ME!
560 public void addAnnotation(AlignmentAnnotation aa)
563 if (annotations != null)
565 aSize = annotations.length + 1;
568 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
570 temp[aSize - 1] = aa;
576 for (i = 0; i < (aSize - 1); i++)
578 temp[i] = annotations[i];
585 public void setAnnotationIndex(AlignmentAnnotation aa, int index)
587 if (aa == null || annotations == null || annotations.length - 1 < index)
592 int aSize = annotations.length;
593 AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];
597 for (int i = 0; i < aSize; i++)
606 temp[i] = annotations[i];
610 temp[i] = annotations[i - 1];
620 * @return DOCUMENT ME!
622 public AlignmentAnnotation[] getAlignmentAnnotation()
627 public void setNucleotide(boolean b)
639 public boolean isNucleotide()
641 if (type == NUCLEOTIDE)
651 public void setDataset(Alignment data)
653 if (dataset == null && data == null)
655 // Create a new dataset for this alignment.
656 // Can only be done once, if dataset is not null
657 // This will not be performed
658 SequenceI[] seqs = new SequenceI[getHeight()];
659 SequenceI currentSeq;
660 for (int i = 0; i < getHeight(); i++)
662 currentSeq = getSequenceAt(i);
663 if (currentSeq.getDatasetSequence() != null)
665 seqs[i] = (Sequence) currentSeq.getDatasetSequence();
669 seqs[i] = currentSeq.createDatasetSequence();
673 dataset = new Alignment(seqs);
675 else if (dataset == null && data != null)
679 dataset.addAlignmentRef();
682 * reference count for number of alignments referencing this one.
686 * increase reference count to this alignment.
688 private void addAlignmentRef()
693 public Alignment getDataset()
698 public boolean padGaps()
700 boolean modified = false;
702 //Remove excess gaps from the end of alignment
706 for (int i = 0; i < sequences.size(); i++)
708 current = getSequenceAt(i);
709 for (int j = current.getLength(); j > maxLength; j--)
711 if (j > maxLength && !jalview.util.Comparison.isGap(
712 current.getCharAt(j)))
723 for (int i = 0; i < sequences.size();
726 current = getSequenceAt(i);
727 cLength = current.getLength();
729 if (cLength < maxLength)
731 current.insertCharAt(cLength,
732 maxLength - cLength, gapCharacter);
735 else if (current.getLength() > maxLength)
737 current.deleteChars(maxLength, current.getLength());
743 public HiddenSequences getHiddenSequences()
745 return hiddenSequences;
748 public CigarArray getCompactAlignment()
750 SeqCigar alseqs[] = new SeqCigar[sequences.size()];
751 for (int i = 0; i < sequences.size(); i++)
753 alseqs[i] = new SeqCigar( (SequenceI) sequences.elementAt(i));
755 CigarArray cal = new CigarArray(alseqs);
756 cal.addOperation(CigarArray.M, getWidth());
760 public void setProperty(Object key, Object value)
762 if(alignmentProperties==null)
763 alignmentProperties = new Hashtable();
765 alignmentProperties.put(key,value);
768 public Object getProperty(Object key)
770 if(alignmentProperties!=null)
771 return alignmentProperties.get(key);
776 public Hashtable getProperties()
778 return alignmentProperties;
780 AlignedCodonFrame[] codonFrameList=null;
782 * @see jalview.datamodel.AlignmentI#addCodonFrame(jalview.datamodel.AlignedCodonFrame)
784 public void addCodonFrame(AlignedCodonFrame codons)
788 if (codonFrameList==null)
790 codonFrameList = new AlignedCodonFrame[] { codons };
793 AlignedCodonFrame[] t = new AlignedCodonFrame[codonFrameList.length+1];
794 System.arraycopy(codonFrameList, 0, t, 0, codonFrameList.length);
795 t[codonFrameList.length] = codons;
800 * @see jalview.datamodel.AlignmentI#getCodonFrame(int)
802 public AlignedCodonFrame getCodonFrame(int index)
804 return codonFrameList[index];
808 * @see jalview.datamodel.AlignmentI#getCodonFrame(jalview.datamodel.SequenceI)
810 public AlignedCodonFrame[] getCodonFrame(SequenceI seq)
812 if (seq==null || codonFrameList==null)
814 Vector cframes=new Vector();
815 for (int f=0;f<codonFrameList.length; f++)
817 if (codonFrameList[f].involvesSequence(seq))
818 cframes.addElement(codonFrameList[f]);
820 if (cframes.size()==0)
822 AlignedCodonFrame[] cfr = new AlignedCodonFrame[cframes.size()];
823 cframes.copyInto(cfr);
828 * @see jalview.datamodel.AlignmentI#getCodonFrames()
830 public AlignedCodonFrame[] getCodonFrames()
832 return codonFrameList;
836 * @see jalview.datamodel.AlignmentI#removeCodonFrame(jalview.datamodel.AlignedCodonFrame)
838 public boolean removeCodonFrame(AlignedCodonFrame codons)
840 if (codons==null || codonFrameList==null)
842 boolean removed=false;
843 int i=0,iSize=codonFrameList.length;
846 if (codonFrameList[i]==codons)
851 System.arraycopy(codonFrameList,i+1,codonFrameList, i, iSize-i-1);