isNucleotide
[jalview.git] / src / jalview / datamodel / Alignment.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.datamodel;\r
20 \r
21 import jalview.analysis.*;\r
22 \r
23 import jalview.util.*;\r
24 \r
25 import java.util.*;\r
26 \r
27 \r
28 /** Data structure to hold and manipulate a multiple sequence alignment\r
29  */\r
30 public class Alignment implements AlignmentI\r
31 {\r
32     protected Vector sequences;\r
33     protected Vector groups = new Vector();\r
34     protected Vector superGroup = new Vector();\r
35     protected char gapCharacter = '-';\r
36     protected boolean isNucleotide = true;\r
37 \r
38 \r
39     /** DOCUMENT ME!! */\r
40     public AlignmentAnnotation[] annotations;\r
41 \r
42     /** DOCUMENT ME!! */\r
43     public boolean featuresAdded = false;\r
44 \r
45     /** Make an alignment from an array of Sequences.\r
46      *\r
47      * @param sequences\r
48      */\r
49     public Alignment(SequenceI[] seqs)\r
50     {\r
51         int i=0, iSize = seqs.length, j, jSize;\r
52         while(isNucleotide && i<iSize)\r
53         {\r
54             jSize = seqs[i].getLength();\r
55             for(j=0; j<jSize; j++)\r
56             {\r
57               if(!jalview.schemes.ResidueProperties.nucleotideHash.containsKey(seqs[i].getSequence(j, j+1))\r
58               && !jalview.util.Comparison.isGap(seqs[i].getSequence().charAt(j)))\r
59               {\r
60                 isNucleotide = false;\r
61                 break;\r
62               }\r
63             }\r
64             i++;\r
65         }\r
66 \r
67         sequences = new Vector();\r
68 \r
69         for (i = 0; i < seqs.length; i++)\r
70         {\r
71             sequences.addElement(seqs[i]);\r
72         }\r
73 \r
74         getWidth();\r
75     }\r
76 \r
77     /**\r
78      * DOCUMENT ME!\r
79      *\r
80      * @return DOCUMENT ME!\r
81      */\r
82     public Vector getSequences()\r
83     {\r
84         return sequences;\r
85     }\r
86 \r
87     /**\r
88      * DOCUMENT ME!\r
89      *\r
90      * @param i DOCUMENT ME!\r
91      *\r
92      * @return DOCUMENT ME!\r
93      */\r
94     public SequenceI getSequenceAt(int i)\r
95     {\r
96         if (i < sequences.size())\r
97         {\r
98             return (SequenceI) sequences.elementAt(i);\r
99         }\r
100 \r
101         return null;\r
102     }\r
103 \r
104     /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
105      *\r
106      * @param snew\r
107      */\r
108     public void addSequence(SequenceI snew)\r
109     {\r
110         sequences.addElement(snew);\r
111     }\r
112 \r
113     /**\r
114      * DOCUMENT ME!\r
115      *\r
116      * @param seq DOCUMENT ME!\r
117      */\r
118     public void addSequence(SequenceI[] seq)\r
119     {\r
120         for (int i = 0; i < seq.length; i++)\r
121         {\r
122             addSequence(seq[i]);\r
123         }\r
124     }\r
125 \r
126     /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
127      *\r
128      * @param snew\r
129      */\r
130     public void setSequenceAt(int i, SequenceI snew)\r
131     {\r
132         SequenceI oldseq = getSequenceAt(i);\r
133         deleteSequence(oldseq);\r
134 \r
135         sequences.setElementAt(snew, i);\r
136     }\r
137 \r
138     /**\r
139      * DOCUMENT ME!\r
140      *\r
141      * @return DOCUMENT ME!\r
142      */\r
143     public Vector getGroups()\r
144     {\r
145         return groups;\r
146     }\r
147 \r
148     /** Takes out columns consisting entirely of gaps (-,.," ")\r
149      */\r
150     public void removeGaps()\r
151     {\r
152         SequenceI current;\r
153         int iSize = getWidth();\r
154 \r
155         for (int i = 0; i < iSize; i++)\r
156         {\r
157             boolean delete = true;\r
158 \r
159             for (int j = 0; j < getHeight(); j++)\r
160             {\r
161                 current = getSequenceAt(j);\r
162 \r
163                 if (current.getLength() > i)\r
164                 {\r
165                     /* MC Should move this to a method somewhere */\r
166                     if (!jalview.util.Comparison.isGap(current.getCharAt(i)))\r
167                     {\r
168                         delete = false;\r
169                     }\r
170                 }\r
171             }\r
172 \r
173             if (delete)\r
174             {\r
175                 deleteColumns(i, i);\r
176                 iSize--;\r
177                 i--;\r
178             }\r
179         }\r
180     }\r
181 \r
182     /** Removes a range of columns (start to end inclusive).\r
183      *\r
184      * @param start Start column in the alignment\r
185      * @param end End column in the alignment\r
186      */\r
187     public void deleteColumns(int start, int end)\r
188     {\r
189         deleteColumns(0, getHeight() - 1, start, end);\r
190     }\r
191 \r
192     /**\r
193      * DOCUMENT ME!\r
194      *\r
195      * @param seq1 DOCUMENT ME!\r
196      * @param seq2 DOCUMENT ME!\r
197      * @param start DOCUMENT ME!\r
198      * @param end DOCUMENT ME!\r
199      */\r
200     public void deleteColumns(int seq1, int seq2, int start, int end)\r
201     {\r
202         for (int i = 0; i <= (end - start); i++)\r
203         {\r
204             for (int j = seq1; j <= seq2; j++)\r
205             {\r
206                 getSequenceAt(j).deleteCharAt(start);\r
207             }\r
208         }\r
209     }\r
210 \r
211     /**\r
212      * DOCUMENT ME!\r
213      *\r
214      * @param i DOCUMENT ME!\r
215      */\r
216     public void trimLeft(int i)\r
217     {\r
218         for (int j = 0; j < getHeight(); j++)\r
219         {\r
220             SequenceI s = getSequenceAt(j);\r
221             int newstart = s.findPosition(i);\r
222 \r
223             s.setStart(newstart);\r
224             s.setSequence(s.getSequence().substring(i));\r
225         }\r
226     }\r
227 \r
228     /**\r
229      * DOCUMENT ME!\r
230      *\r
231      * @param i DOCUMENT ME!\r
232      */\r
233     public void trimRight(int i)\r
234     {\r
235         for (int j = 0; j < getHeight(); j++)\r
236         {\r
237             SequenceI s = getSequenceAt(j);\r
238             int newend = s.findPosition(i);\r
239 \r
240             s.setEnd(newend);\r
241             s.setSequence(s.getSequence().substring(0, i + 1));\r
242         }\r
243     }\r
244 \r
245     /**\r
246      * DOCUMENT ME!\r
247      *\r
248      * @param s DOCUMENT ME!\r
249      */\r
250     public void deleteSequence(SequenceI s)\r
251     {\r
252         for (int i = 0; i < getHeight(); i++)\r
253         {\r
254             if (getSequenceAt(i) == s)\r
255             {\r
256                 deleteSequence(i);\r
257             }\r
258         }\r
259     }\r
260 \r
261     /**\r
262      * DOCUMENT ME!\r
263      *\r
264      * @param i DOCUMENT ME!\r
265      */\r
266     public void deleteSequence(int i)\r
267     {\r
268         sequences.removeElementAt(i);\r
269     }\r
270 \r
271     /**\r
272      * DOCUMENT ME!\r
273      *\r
274      * @param threshold DOCUMENT ME!\r
275      * @param sel DOCUMENT ME!\r
276      *\r
277      * @return DOCUMENT ME!\r
278      */\r
279     public Vector removeRedundancy(float threshold, Vector sel)\r
280     {\r
281         Vector del = new Vector();\r
282 \r
283         for (int i = 1; i < sel.size(); i++)\r
284         {\r
285             for (int j = 0; j < i; j++)\r
286             {\r
287                 // Only do the comparison if either have not been deleted\r
288                 if (!del.contains((SequenceI) sel.elementAt(i)) ||\r
289                         !del.contains((SequenceI) sel.elementAt(j)))\r
290                 {\r
291                     // use PID instead of Comparison (which is really not pleasant)\r
292                     float pid = Comparison.PID((SequenceI) sel.elementAt(j),\r
293                             (SequenceI) sel.elementAt(i));\r
294 \r
295                     if (pid >= threshold)\r
296                     {\r
297                         // Delete the shortest one\r
298                         if (((SequenceI) sel.elementAt(j)).getSequence().length() > ((SequenceI) sel\r
299                                                                                          .elementAt(\r
300                                     i)).getSequence().length())\r
301                         {\r
302                             del.addElement(sel.elementAt(i));\r
303                         }\r
304                         else\r
305                         {\r
306                             del.addElement(sel.elementAt(i));\r
307                         }\r
308                     }\r
309                 }\r
310             }\r
311         }\r
312 \r
313         // Now delete the sequences\r
314         for (int i = 0; i < del.size(); i++)\r
315         {\r
316             deleteSequence((SequenceI) del.elementAt(i));\r
317         }\r
318 \r
319         return del;\r
320     }\r
321 \r
322     /**    */\r
323     public SequenceGroup findGroup(int i)\r
324     {\r
325         return findGroup(getSequenceAt(i));\r
326     }\r
327 \r
328     /**    */\r
329     public SequenceGroup findGroup(SequenceI s)\r
330     {\r
331         for (int i = 0; i < this.groups.size(); i++)\r
332         {\r
333             SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
334 \r
335             if (sg.sequences.contains(s))\r
336             {\r
337                 return sg;\r
338             }\r
339         }\r
340 \r
341         return null;\r
342     }\r
343 \r
344     /**\r
345      * DOCUMENT ME!\r
346      *\r
347      * @param s DOCUMENT ME!\r
348      *\r
349      * @return DOCUMENT ME!\r
350      */\r
351     public SequenceGroup[] findAllGroups(SequenceI s)\r
352     {\r
353         Vector temp = new Vector();\r
354 \r
355         int gSize = groups.size();\r
356         for (int i = 0; i < gSize; i++)\r
357         {\r
358             SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
359             if(sg==null || sg.sequences==null)\r
360             {\r
361               this.deleteGroup(sg);\r
362               gSize--;\r
363               continue;\r
364             }\r
365 \r
366             if (sg.sequences.contains(s))\r
367             {\r
368                 temp.addElement(sg);\r
369             }\r
370         }\r
371 \r
372         SequenceGroup[] ret = new SequenceGroup[temp.size()];\r
373 \r
374         for (int i = 0; i < temp.size(); i++)\r
375         {\r
376             ret[i] = (SequenceGroup) temp.elementAt(i);\r
377         }\r
378 \r
379         return ret;\r
380     }\r
381 \r
382     /**\r
383      * DOCUMENT ME!\r
384      *\r
385      * @param sg DOCUMENT ME!\r
386      */\r
387     public void addSuperGroup(SuperGroup sg)\r
388     {\r
389         superGroup.addElement(sg);\r
390     }\r
391 \r
392     /**\r
393      * DOCUMENT ME!\r
394      *\r
395      * @param sg DOCUMENT ME!\r
396      */\r
397     public void removeSuperGroup(SuperGroup sg)\r
398     {\r
399         superGroup.removeElement(sg);\r
400     }\r
401 \r
402     /**\r
403      * DOCUMENT ME!\r
404      *\r
405      * @param sg DOCUMENT ME!\r
406      *\r
407      * @return DOCUMENT ME!\r
408      */\r
409     public SuperGroup getSuperGroup(SequenceGroup sg)\r
410     {\r
411         for (int i = 0; i < this.superGroup.size(); i++)\r
412         {\r
413             SuperGroup temp = (SuperGroup) superGroup.elementAt(i);\r
414 \r
415             if (temp.sequenceGroups.contains(sg))\r
416             {\r
417                 return temp;\r
418             }\r
419         }\r
420 \r
421         return null;\r
422     }\r
423 \r
424     /**    */\r
425     public void addGroup(SequenceGroup sg)\r
426     {\r
427         if (!groups.contains(sg))\r
428         {\r
429             groups.addElement(sg);\r
430         }\r
431     }\r
432 \r
433     /**\r
434      * DOCUMENT ME!\r
435      */\r
436     public void deleteAllGroups()\r
437     {\r
438         groups.removeAllElements();\r
439         superGroup.removeAllElements();\r
440 \r
441         int i = 0;\r
442 \r
443         while (i < sequences.size())\r
444         {\r
445             SequenceI s = getSequenceAt(i);\r
446             s.setColor(java.awt.Color.white);\r
447             i++;\r
448         }\r
449     }\r
450 \r
451     /**    */\r
452     public void deleteGroup(SequenceGroup g)\r
453     {\r
454         if (groups.contains(g))\r
455         {\r
456             groups.removeElement(g);\r
457         }\r
458     }\r
459 \r
460     /**    */\r
461     public SequenceI findName(String name)\r
462     {\r
463         int i = 0;\r
464 \r
465         while (i < sequences.size())\r
466         {\r
467             SequenceI s = getSequenceAt(i);\r
468 \r
469             if (s.getName().equals(name))\r
470             {\r
471                 return s;\r
472             }\r
473 \r
474             i++;\r
475         }\r
476 \r
477         return null;\r
478     }\r
479 \r
480     /**    */\r
481     public SequenceI findbyDisplayId(String name)\r
482     {\r
483         int i = 0;\r
484 \r
485         while (i < sequences.size())\r
486         {\r
487             SequenceI s = getSequenceAt(i);\r
488 \r
489             if (s.getDisplayId().equals(name))\r
490             {\r
491                 return s;\r
492             }\r
493 \r
494             i++;\r
495         }\r
496 \r
497         return null;\r
498     }\r
499 \r
500     /**    */\r
501     public int findIndex(SequenceI s)\r
502     {\r
503         int i = 0;\r
504 \r
505         while (i < sequences.size())\r
506         {\r
507             if (s == getSequenceAt(i))\r
508             {\r
509                 return i;\r
510             }\r
511 \r
512             i++;\r
513         }\r
514 \r
515         return -1;\r
516     }\r
517 \r
518     /**\r
519      * DOCUMENT ME!\r
520      *\r
521      * @return DOCUMENT ME!\r
522      */\r
523     public int getHeight()\r
524     {\r
525         return sequences.size();\r
526     }\r
527 \r
528     /**\r
529      * DOCUMENT ME!\r
530      *\r
531      * @return DOCUMENT ME!\r
532      */\r
533     public int getWidth()\r
534     {\r
535         int maxLength = -1;\r
536 \r
537         for (int i = 0; i < sequences.size(); i++)\r
538         {\r
539             if (getSequenceAt(i).getLength() > maxLength)\r
540             {\r
541                 maxLength = getSequenceAt(i).getLength();\r
542             }\r
543         }\r
544 \r
545         return maxLength;\r
546     }\r
547 \r
548     /**\r
549      * DOCUMENT ME!\r
550      *\r
551      * @return DOCUMENT ME!\r
552      */\r
553     public int getMaxIdLength()\r
554     {\r
555         int max = 0;\r
556         int i = 0;\r
557 \r
558         while (i < sequences.size())\r
559         {\r
560             SequenceI seq = getSequenceAt(i);\r
561             String tmp = seq.getName() + "/" + seq.getStart() + "-" +\r
562                 seq.getEnd();\r
563 \r
564             if (tmp.length() > max)\r
565             {\r
566                 max = tmp.length();\r
567             }\r
568 \r
569             i++;\r
570         }\r
571 \r
572         return max;\r
573     }\r
574 \r
575     /**\r
576      * DOCUMENT ME!\r
577      *\r
578      * @param gc DOCUMENT ME!\r
579      */\r
580     public void setGapCharacter(char gc)\r
581     {\r
582         gapCharacter = gc;\r
583 \r
584         for (int i = 0; i < sequences.size(); i++)\r
585         {\r
586             Sequence seq = (Sequence) sequences.elementAt(i);\r
587             seq.sequence = seq.sequence.replace('.', gc);\r
588             seq.sequence = seq.sequence.replace('-', gc);\r
589             seq.sequence = seq.sequence.replace(' ', gc);\r
590         }\r
591     }\r
592 \r
593     /**\r
594      * DOCUMENT ME!\r
595      *\r
596      * @return DOCUMENT ME!\r
597      */\r
598     public char getGapCharacter()\r
599     {\r
600         return gapCharacter;\r
601     }\r
602 \r
603     /**\r
604      * DOCUMENT ME!\r
605      *\r
606      * @return DOCUMENT ME!\r
607      */\r
608     public Vector getAAFrequency()\r
609     {\r
610         return AAFrequency.calculate(sequences, 0, getWidth());\r
611     }\r
612 \r
613     /**\r
614      * DOCUMENT ME!\r
615      *\r
616      * @return DOCUMENT ME!\r
617      */\r
618     public boolean isAligned()\r
619     {\r
620         int width = getWidth();\r
621 \r
622         for (int i = 0; i < sequences.size(); i++)\r
623         {\r
624             if (getSequenceAt(i).getLength() != width)\r
625             {\r
626                 return false;\r
627             }\r
628         }\r
629 \r
630         return true;\r
631     }\r
632 \r
633     /**\r
634      * DOCUMENT ME!\r
635      *\r
636      * @param aa DOCUMENT ME!\r
637      */\r
638     public void deleteAnnotation(AlignmentAnnotation aa)\r
639     {\r
640         int aSize = 1;\r
641 \r
642         if (annotations != null)\r
643         {\r
644             aSize = annotations.length;\r
645         }\r
646 \r
647         AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];\r
648 \r
649         int tIndex = 0;\r
650 \r
651         for (int i = 0; i < aSize; i++)\r
652         {\r
653             if (annotations[i] == aa)\r
654             {\r
655                 continue;\r
656             }\r
657 \r
658             temp[tIndex] = annotations[i];\r
659             tIndex++;\r
660         }\r
661 \r
662         annotations = temp;\r
663     }\r
664 \r
665     /**\r
666      * DOCUMENT ME!\r
667      *\r
668      * @param aa DOCUMENT ME!\r
669      */\r
670     public void addAnnotation(AlignmentAnnotation aa)\r
671     {\r
672         int aSize = 1;\r
673 \r
674         if (annotations != null)\r
675         {\r
676             aSize = annotations.length + 1;\r
677         }\r
678 \r
679         AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];\r
680         int i = 0;\r
681 \r
682         if (aSize > 1)\r
683         {\r
684             for (i = 0; i < (aSize - 1); i++)\r
685             {\r
686                 temp[i] = annotations[i];\r
687             }\r
688         }\r
689 \r
690         temp[i] = aa;\r
691 \r
692         annotations = temp;\r
693     }\r
694 \r
695     /**\r
696      * DOCUMENT ME!\r
697      *\r
698      * @return DOCUMENT ME!\r
699      */\r
700     public AlignmentAnnotation[] getAlignmentAnnotation()\r
701     {\r
702         return annotations;\r
703     }\r
704 \r
705     public void setNucleotide(boolean b)\r
706     {\r
707       isNucleotide = b;\r
708     }\r
709 \r
710     public boolean isNucleotide()\r
711     {\r
712       return isNucleotide;\r
713     }\r
714 }\r