Add annotation with sequence ref updated
[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 Alignment dataset;\r
33     protected Vector sequences;\r
34     protected Vector groups = new Vector();\r
35     protected Vector superGroup = new Vector();\r
36     protected char gapCharacter = '-';\r
37     protected int type = NUCLEOTIDE;\r
38     public static final int PROTEIN = 0;\r
39     public static final int NUCLEOTIDE = 1;\r
40 \r
41     /** DOCUMENT ME!! */\r
42     public AlignmentAnnotation[] annotations;\r
43 \r
44     /** Make an alignment from an array of Sequences.\r
45      *\r
46      * @param sequences\r
47      */\r
48     public Alignment(SequenceI[] seqs)\r
49     {\r
50         int i=0;\r
51 \r
52         if( jalview.util.Comparison.isNucleotide(seqs))\r
53           type = NUCLEOTIDE;\r
54         else\r
55           type = PROTEIN;\r
56 \r
57         sequences = new Vector();\r
58 \r
59         for (i = 0; i < seqs.length; i++)\r
60         {\r
61             sequences.addElement(seqs[i]);\r
62 \r
63             if(seqs[i].getDatasetSequence()!=null\r
64             && seqs[i].getDatasetSequence().getAnnotation()!=null)\r
65             {\r
66 \r
67               for(int a=0; a<seqs[i].getDatasetSequence().getAnnotation().length; a++)\r
68               {\r
69                        this.addAnnotation(seqs[i].getDatasetSequence().getAnnotation()[a], seqs[i]);\r
70               }\r
71             }\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         int j, jSize = getHeight();\r
219         for (j = 0; j < jSize; j++)\r
220         {\r
221             SequenceI s = getSequenceAt(j);\r
222             int newstart = s.findPosition(i);\r
223 \r
224             if(i>s.getLength())\r
225             {\r
226               sequences.removeElement(s);\r
227               j--;\r
228               jSize--;\r
229             }\r
230             else\r
231             {\r
232               s.setStart(newstart);\r
233               s.setSequence(s.getSequence().substring(i));\r
234             }\r
235         }\r
236     }\r
237 \r
238     /**\r
239      * DOCUMENT ME!\r
240      *\r
241      * @param i DOCUMENT ME!\r
242      */\r
243     public void trimRight(int i)\r
244     {\r
245         for (int j = 0; j < getHeight(); j++)\r
246         {\r
247             SequenceI s = getSequenceAt(j);\r
248             int newend = s.findPosition(i);\r
249 \r
250             s.setEnd(newend);\r
251             if(s.getLength()>i)\r
252               s.setSequence(s.getSequence().substring(0, i + 1));\r
253         }\r
254     }\r
255 \r
256     /**\r
257      * DOCUMENT ME!\r
258      *\r
259      * @param s DOCUMENT ME!\r
260      */\r
261     public void deleteSequence(SequenceI s)\r
262     {\r
263         for (int i = 0; i < getHeight(); i++)\r
264         {\r
265             if (getSequenceAt(i) == s)\r
266             {\r
267                 deleteSequence(i);\r
268             }\r
269         }\r
270     }\r
271 \r
272     /**\r
273      * DOCUMENT ME!\r
274      *\r
275      * @param i DOCUMENT ME!\r
276      */\r
277     public void deleteSequence(int i)\r
278     {\r
279         sequences.removeElementAt(i);\r
280     }\r
281 \r
282     /**\r
283      * DOCUMENT ME!\r
284      *\r
285      * @param threshold DOCUMENT ME!\r
286      * @param sel DOCUMENT ME!\r
287      *\r
288      * @return DOCUMENT ME!\r
289      */\r
290     public Vector removeRedundancy(float threshold, Vector sel)\r
291     {\r
292         Vector del = new Vector();\r
293 \r
294         for (int i = 1; i < sel.size(); i++)\r
295         {\r
296             for (int j = 0; j < i; j++)\r
297             {\r
298                 // Only do the comparison if either have not been deleted\r
299                 if (!del.contains((SequenceI) sel.elementAt(i)) ||\r
300                         !del.contains((SequenceI) sel.elementAt(j)))\r
301                 {\r
302                     // use PID instead of Comparison (which is really not pleasant)\r
303                     float pid = Comparison.PID((SequenceI) sel.elementAt(j),\r
304                             (SequenceI) sel.elementAt(i));\r
305 \r
306                     if (pid >= threshold)\r
307                     {\r
308                         // Delete the shortest one\r
309                         if (((SequenceI) sel.elementAt(j)).getSequence().length() > ((SequenceI) sel\r
310                                                                                          .elementAt(\r
311                                     i)).getSequence().length())\r
312                         {\r
313                             del.addElement(sel.elementAt(i));\r
314                         }\r
315                         else\r
316                         {\r
317                             del.addElement(sel.elementAt(i));\r
318                         }\r
319                     }\r
320                 }\r
321             }\r
322         }\r
323 \r
324         // Now delete the sequences\r
325         for (int i = 0; i < del.size(); i++)\r
326         {\r
327             deleteSequence((SequenceI) del.elementAt(i));\r
328         }\r
329 \r
330         return del;\r
331     }\r
332 \r
333     /**    */\r
334     public SequenceGroup findGroup(int i)\r
335     {\r
336         return findGroup(getSequenceAt(i));\r
337     }\r
338 \r
339     /**    */\r
340     public SequenceGroup findGroup(SequenceI s)\r
341     {\r
342         for (int i = 0; i < this.groups.size(); i++)\r
343         {\r
344             SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
345 \r
346             if (sg.sequences.contains(s))\r
347             {\r
348                 return sg;\r
349             }\r
350         }\r
351 \r
352         return null;\r
353     }\r
354 \r
355     /**\r
356      * DOCUMENT ME!\r
357      *\r
358      * @param s DOCUMENT ME!\r
359      *\r
360      * @return DOCUMENT ME!\r
361      */\r
362     public SequenceGroup[] findAllGroups(SequenceI s)\r
363     {\r
364         Vector temp = new Vector();\r
365 \r
366         int gSize = groups.size();\r
367         for (int i = 0; i < gSize; i++)\r
368         {\r
369             SequenceGroup sg = (SequenceGroup) groups.elementAt(i);\r
370             if(sg==null || sg.sequences==null)\r
371             {\r
372               this.deleteGroup(sg);\r
373               gSize--;\r
374               continue;\r
375             }\r
376 \r
377             if (sg.sequences.contains(s))\r
378             {\r
379                 temp.addElement(sg);\r
380             }\r
381         }\r
382 \r
383         SequenceGroup[] ret = new SequenceGroup[temp.size()];\r
384 \r
385         for (int i = 0; i < temp.size(); i++)\r
386         {\r
387             ret[i] = (SequenceGroup) temp.elementAt(i);\r
388         }\r
389 \r
390         return ret;\r
391     }\r
392 \r
393     /**\r
394      * DOCUMENT ME!\r
395      *\r
396      * @param sg DOCUMENT ME!\r
397      */\r
398     public void addSuperGroup(SuperGroup sg)\r
399     {\r
400         superGroup.addElement(sg);\r
401     }\r
402 \r
403     /**\r
404      * DOCUMENT ME!\r
405      *\r
406      * @param sg DOCUMENT ME!\r
407      */\r
408     public void removeSuperGroup(SuperGroup sg)\r
409     {\r
410         superGroup.removeElement(sg);\r
411     }\r
412 \r
413     /**\r
414      * DOCUMENT ME!\r
415      *\r
416      * @param sg DOCUMENT ME!\r
417      *\r
418      * @return DOCUMENT ME!\r
419      */\r
420     public SuperGroup getSuperGroup(SequenceGroup sg)\r
421     {\r
422         for (int i = 0; i < this.superGroup.size(); i++)\r
423         {\r
424             SuperGroup temp = (SuperGroup) superGroup.elementAt(i);\r
425 \r
426             if (temp.sequenceGroups.contains(sg))\r
427             {\r
428                 return temp;\r
429             }\r
430         }\r
431 \r
432         return null;\r
433     }\r
434 \r
435     /**    */\r
436     public void addGroup(SequenceGroup sg)\r
437     {\r
438         if (!groups.contains(sg))\r
439         {\r
440             groups.addElement(sg);\r
441         }\r
442     }\r
443 \r
444     /**\r
445      * DOCUMENT ME!\r
446      */\r
447     public void deleteAllGroups()\r
448     {\r
449         groups.removeAllElements();\r
450         superGroup.removeAllElements();\r
451 \r
452         int i = 0;\r
453 \r
454         while (i < sequences.size())\r
455         {\r
456             SequenceI s = getSequenceAt(i);\r
457             s.setColor(java.awt.Color.white);\r
458             i++;\r
459         }\r
460     }\r
461 \r
462     /**    */\r
463     public void deleteGroup(SequenceGroup g)\r
464     {\r
465         if (groups.contains(g))\r
466         {\r
467             groups.removeElement(g);\r
468         }\r
469     }\r
470 \r
471     /**    */\r
472     public SequenceI findName(String name)\r
473     {\r
474         int i = 0;\r
475 \r
476         while (i < sequences.size())\r
477         {\r
478             if (getSequenceAt(i).getName().equals(name))\r
479             {\r
480                 return getSequenceAt(i);\r
481             }\r
482 \r
483             i++;\r
484         }\r
485 \r
486         return null;\r
487     }\r
488 \r
489 \r
490     /**    */\r
491     public int findIndex(SequenceI s)\r
492     {\r
493         int i = 0;\r
494 \r
495         while (i < sequences.size())\r
496         {\r
497             if (s == getSequenceAt(i))\r
498             {\r
499                 return i;\r
500             }\r
501 \r
502             i++;\r
503         }\r
504 \r
505         return -1;\r
506     }\r
507 \r
508     /**\r
509      * DOCUMENT ME!\r
510      *\r
511      * @return DOCUMENT ME!\r
512      */\r
513     public int getHeight()\r
514     {\r
515         return sequences.size();\r
516     }\r
517 \r
518     /**\r
519      * DOCUMENT ME!\r
520      *\r
521      * @return DOCUMENT ME!\r
522      */\r
523     public int getWidth()\r
524     {\r
525         int maxLength = -1;\r
526 \r
527         for (int i = 0; i < sequences.size(); i++)\r
528         {\r
529             if (getSequenceAt(i).getLength() > maxLength)\r
530             {\r
531                 maxLength = getSequenceAt(i).getLength();\r
532             }\r
533         }\r
534 \r
535         return maxLength;\r
536     }\r
537 \r
538     /**\r
539      * DOCUMENT ME!\r
540      *\r
541      * @return DOCUMENT ME!\r
542      */\r
543     public int getMaxIdLength()\r
544     {\r
545         int max = 0;\r
546         int i = 0;\r
547 \r
548         while (i < sequences.size())\r
549         {\r
550             SequenceI seq = getSequenceAt(i);\r
551             String tmp = seq.getName() + "/" + seq.getStart() + "-" +\r
552                 seq.getEnd();\r
553 \r
554             if (tmp.length() > max)\r
555             {\r
556                 max = tmp.length();\r
557             }\r
558 \r
559             i++;\r
560         }\r
561 \r
562         return max;\r
563     }\r
564 \r
565     /**\r
566      * DOCUMENT ME!\r
567      *\r
568      * @param gc DOCUMENT ME!\r
569      */\r
570     public void setGapCharacter(char gc)\r
571     {\r
572         gapCharacter = gc;\r
573 \r
574         for (int i = 0; i < sequences.size(); i++)\r
575         {\r
576             Sequence seq = (Sequence) sequences.elementAt(i);\r
577             seq.sequence = seq.sequence.replace('.', gc);\r
578             seq.sequence = seq.sequence.replace('-', gc);\r
579             seq.sequence = seq.sequence.replace(' ', gc);\r
580         }\r
581     }\r
582 \r
583     /**\r
584      * DOCUMENT ME!\r
585      *\r
586      * @return DOCUMENT ME!\r
587      */\r
588     public char getGapCharacter()\r
589     {\r
590         return gapCharacter;\r
591     }\r
592 \r
593     /**\r
594      * DOCUMENT ME!\r
595      *\r
596      * @return DOCUMENT ME!\r
597      */\r
598     public Vector getAAFrequency()\r
599     {\r
600         return AAFrequency.calculate(sequences, 0, getWidth());\r
601     }\r
602 \r
603     /**\r
604      * DOCUMENT ME!\r
605      *\r
606      * @return DOCUMENT ME!\r
607      */\r
608     public boolean isAligned()\r
609     {\r
610         int width = getWidth();\r
611 \r
612         for (int i = 0; i < sequences.size(); i++)\r
613         {\r
614             if (getSequenceAt(i).getLength() != width)\r
615             {\r
616                 return false;\r
617             }\r
618         }\r
619 \r
620         return true;\r
621     }\r
622 \r
623     /**\r
624      * DOCUMENT ME!\r
625      *\r
626      * @param aa DOCUMENT ME!\r
627      */\r
628     public void deleteAnnotation(AlignmentAnnotation aa)\r
629     {\r
630         int aSize = 1;\r
631 \r
632         if (annotations != null)\r
633         {\r
634             aSize = annotations.length;\r
635         }\r
636 \r
637         AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize - 1];\r
638 \r
639         int tIndex = 0;\r
640 \r
641         for (int i = 0; i < aSize; i++)\r
642         {\r
643             if (annotations[i] == aa)\r
644             {\r
645                 continue;\r
646             }\r
647 \r
648             temp[tIndex] = annotations[i];\r
649             tIndex++;\r
650         }\r
651 \r
652         annotations = temp;\r
653     }\r
654 \r
655     /**\r
656      *\r
657      * @param aa AlignmentAnnotation\r
658      * @param seqRef The sequence to associate this annotation with\r
659      * @return The adjusted AlignmentAnnotation, with dataset sequence and annotation added\r
660      */\r
661     public AlignmentAnnotation addAnnotation(AlignmentAnnotation aa, SequenceI seqRef)\r
662     {\r
663       if(seqRef!=null)\r
664       {\r
665           //We can only add Annotations to the dataset sequences\r
666            if(seqRef.getDatasetSequence()==null)\r
667            {\r
668                   setDataset(null);\r
669             }\r
670 \r
671         AlignmentAnnotation []  old = seqRef.getDatasetSequence().getAnnotation();\r
672 \r
673         //First check if this is a new annotation or not. If it is new,\r
674         //we must add the annotation to the dataset\r
675         boolean newAnnotation = true;\r
676         if(seqRef.getDatasetSequence().getAnnotation()!=null)\r
677         {\r
678           for(int a=0; a<old.length; a++)\r
679           {\r
680             if(old[a] == aa)\r
681             {\r
682 \r
683               newAnnotation = false;\r
684               break;\r
685             }\r
686           }\r
687         }\r
688 \r
689         if(newAnnotation)\r
690          {\r
691            seqRef.getDatasetSequence().addAlignmentAnnotation(aa);\r
692          }\r
693 \r
694           AlignmentAnnotation copy = null;\r
695           if (aa.graph > 0)\r
696             copy = new AlignmentAnnotation(\r
697                 aa.label, aa.description, aa.annotations, aa.graphMin,\r
698                 aa.graphMax, aa.graph\r
699                 );\r
700           else\r
701             copy = new AlignmentAnnotation(\r
702                 aa.label, aa.description, aa.annotations\r
703                 );\r
704 \r
705          copy.datasetAnnotation = aa;\r
706 \r
707          addAnnotation(copy);\r
708 \r
709          copy.sequenceRef = seqRef;\r
710 \r
711          return copy;\r
712       }\r
713       else\r
714       {\r
715         addAnnotation(aa);\r
716         return aa;\r
717       }\r
718     }\r
719 \r
720     public void adjustSequenceAnnotations()\r
721     {\r
722       if(annotations!=null)\r
723       {\r
724         for (int a = 0; a < annotations.length; a++)\r
725         {\r
726           if (annotations[a].sequenceRef != null)\r
727           {\r
728             annotations[a].adjustForAlignment();\r
729           }\r
730         }\r
731       }\r
732     }\r
733 \r
734     /**\r
735      * DOCUMENT ME!\r
736      *\r
737      * @param aa DOCUMENT ME!\r
738      */\r
739     public void addAnnotation(AlignmentAnnotation aa)\r
740     {\r
741         int aSize = 1;\r
742         if (annotations != null)\r
743         {\r
744             aSize = annotations.length + 1;\r
745         }\r
746 \r
747         AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];\r
748 \r
749         temp[aSize-1] = aa;\r
750 \r
751         int i = 0;\r
752 \r
753         if (aSize > 1)\r
754         {\r
755             for (i = 0; i < (aSize-1); i++)\r
756             {\r
757                 temp[i] = annotations[i];\r
758             }\r
759         }\r
760 \r
761         annotations = temp;\r
762     }\r
763 \r
764     public void setAnnotationIndex(AlignmentAnnotation aa, int index)\r
765     {\r
766       if(aa==null || annotations==null || annotations.length-1<index)\r
767         return;\r
768 \r
769       int aSize = annotations.length;\r
770       AlignmentAnnotation[] temp = new AlignmentAnnotation[aSize];\r
771 \r
772       temp[index] = aa;\r
773 \r
774       for (int i = 0; i < aSize; i++)\r
775       {\r
776         if(i==index)\r
777           continue;\r
778 \r
779         if(i<index)\r
780           temp[i] = annotations[i];\r
781         else\r
782           temp[i] = annotations[i-1];\r
783       }\r
784 \r
785         annotations = temp;\r
786     }\r
787 \r
788     /**\r
789      * DOCUMENT ME!\r
790      *\r
791      * @return DOCUMENT ME!\r
792      */\r
793     public AlignmentAnnotation[] getAlignmentAnnotation()\r
794     {\r
795         return annotations;\r
796     }\r
797 \r
798     public void setNucleotide(boolean b)\r
799     {\r
800       if(b)\r
801         type = NUCLEOTIDE;\r
802       else\r
803         type = PROTEIN;\r
804     }\r
805 \r
806     public boolean isNucleotide()\r
807     {\r
808       if(type==NUCLEOTIDE)\r
809         return true;\r
810       else\r
811         return false;\r
812     }\r
813 \r
814     public void setDataset(Alignment data)\r
815     {\r
816       if(dataset==null && data==null)\r
817       {\r
818         // Create a new dataset for this alignment.\r
819         // Can only be done once, if dataset is not null\r
820         // This will not be performed\r
821         Sequence[] seqs = new Sequence[getHeight()];\r
822         for (int i = 0; i < getHeight(); i++)\r
823         {\r
824 \r
825           seqs[i] = new Sequence(getSequenceAt(i).getName(),\r
826                                  AlignSeq.extractGaps(\r
827                                      jalview.util.Comparison.GapChars,\r
828                                      getSequenceAt(i).getSequence()\r
829                                  ),\r
830                                  getSequenceAt(i).getStart(),\r
831                                  getSequenceAt(i).getEnd());\r
832 \r
833           getSequenceAt(i).setDatasetSequence(seqs[i]);\r
834         }\r
835 \r
836         dataset = new Alignment(seqs);\r
837       }\r
838       else if(dataset==null && data!=null)\r
839       {\r
840         dataset = data;\r
841       }\r
842     }\r
843 \r
844     public Alignment getDataset()\r
845     {\r
846       return dataset;\r
847     }\r
848 \r
849     public boolean padGaps() {\r
850       boolean modified=false;\r
851       int Width = getWidth();\r
852       SequenceI current;\r
853       for (int i = 0; i < sequences.size();\r
854            i++)\r
855       {\r
856         current = getSequenceAt(i);\r
857 \r
858         if (current.getLength() < Width)\r
859         {\r
860           current.insertCharAt(Width - 1, gapCharacter);\r
861           modified=true;\r
862         }\r
863       }\r
864       return modified;\r
865     }\r
866 }\r