1.1 compatible
[jalview.git] / src / jalview / datamodel / Alignment.java
1 package jalview.datamodel;\r
2 \r
3 import jalview.analysis.*;\r
4 import jalview.util.*;\r
5 import java.util.*;\r
6 \r
7 /** Data structure to hold and manipulate a multiple sequence alignment\r
8  */\r
9 public class Alignment implements AlignmentI\r
10 {\r
11 \r
12   protected Vector      sequences;\r
13   protected Vector      groups = new Vector();\r
14   protected Vector   superGroup = new Vector();\r
15   protected char        gapCharacter = '-';\r
16   public AlignmentAnnotation [] annotations;\r
17   public Conservation conservation;\r
18 \r
19   public boolean featuresAdded = false;\r
20 \r
21   /** Make an alignment from an array of Sequences.\r
22   *\r
23   * @param sequences\r
24   */\r
25   public Alignment(SequenceI[] seqs) {\r
26     sequences = new Vector();\r
27 \r
28     for (int i=0; i < seqs.length; i++)\r
29       sequences.addElement(seqs[i]);\r
30 \r
31     getWidth();\r
32   }\r
33 \r
34   public Vector      getSequences() {\r
35     return sequences;\r
36   }\r
37 \r
38   public SequenceI getSequenceAt(int i) {\r
39     if (i < sequences.size()) {\r
40       return (SequenceI)sequences.elementAt(i);\r
41     }\r
42 \r
43     return null;\r
44   }\r
45 \r
46   /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
47    *\r
48    * @param snew\r
49    */\r
50   public void addSequence(SequenceI snew) {\r
51     sequences.addElement(snew);\r
52   }\r
53 \r
54   public void addSequence(SequenceI[] seq) {\r
55     for (int i=0; i < seq.length; i++) {\r
56       addSequence(seq[i]);\r
57     }\r
58   }\r
59 \r
60   /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
61     *\r
62    * @param snew\r
63    */\r
64   public void setSequenceAt(int i,SequenceI snew) {\r
65     SequenceI oldseq = getSequenceAt(i);\r
66     deleteSequence(oldseq);\r
67 \r
68     sequences.setElementAt(snew,i);\r
69   }\r
70 \r
71   public Vector getGroups() {\r
72     return groups;\r
73   }\r
74 \r
75   /** Sorts the sequences by sequence group size - largest to smallest.\r
76    * Uses QuickSort.\r
77    */\r
78   public void sortGroups() {\r
79     float[]  arr = new float [groups.size()];\r
80     Object[] s   = new Object[groups.size()];\r
81 \r
82     for (int i=0; i < groups.size(); i++) {\r
83       arr[i] = ((SequenceGroup)groups.elementAt(i)).sequences.size();\r
84       s[i]   = groups.elementAt(i);\r
85     }\r
86 \r
87     QuickSort.sort(arr,s);\r
88 \r
89     Vector newg = new Vector(groups.size());\r
90 \r
91     for (int i=groups.size()-1; i >= 0; i--) {\r
92       newg.addElement(s[i]);\r
93     }\r
94 \r
95     groups = newg;\r
96   }\r
97 \r
98   /** Takes out columns consisting entirely of gaps (-,.," ")\r
99    */\r
100   public void removeGaps()\r
101   {\r
102 \r
103     SequenceI current;\r
104     int iSize = getWidth();\r
105     for (int i=0; i < iSize; i++)\r
106     {\r
107       boolean delete = true;\r
108       for (int j=0; j < getHeight(); j++)\r
109       {\r
110         current = getSequenceAt(j);\r
111         if (current.getLength() > i)\r
112         {\r
113             /* MC Should move this to a method somewhere */\r
114           if ( !jalview.util.Comparison.isGap(current.getCharAt(i)))\r
115             delete = false;\r
116 \r
117         }\r
118       }\r
119 \r
120       if ( delete )\r
121       {\r
122         deleteColumns(i,i);\r
123         iSize--;\r
124         i--;\r
125       }\r
126     }\r
127 \r
128 \r
129   }\r
130 \r
131   /** Returns an array of Sequences containing columns\r
132    * start to end (inclusive) only.\r
133    *\r
134    * @param start start column to fetch\r
135    * @param end end column to fetch\r
136    * @return Array of Sequences, ready to put into a new Alignment\r
137    */\r
138   public SequenceI[] getColumns(int start, int end) {\r
139     return getColumns(0,getHeight()-1,start,end);\r
140   }\r
141 \r
142   /** Removes a range of columns (start to end inclusive).\r
143    *\r
144    * @param start Start column in the alignment\r
145    * @param end End column in the alignment\r
146    */\r
147   public void deleteColumns(int start, int end) {\r
148     deleteColumns(0,getHeight()-1,start,end);\r
149   }\r
150 \r
151   public void deleteColumns(int seq1, int seq2, int start, int end) {\r
152 \r
153     for (int i=0; i <= (end-start); i++) {\r
154       for (int j=seq1; j <= seq2; j++) {\r
155         getSequenceAt(j).deleteCharAt(start);\r
156       }\r
157     }\r
158   }\r
159 \r
160   public void insertColumns(SequenceI[] seqs, int pos) {\r
161     if (seqs.length == getHeight()) {\r
162       for (int i=0; i < getHeight();i++) {\r
163         String tmp = new String(getSequenceAt(i).getSequence());\r
164         getSequenceAt(i).setSequence(tmp.substring(0,pos) + seqs[i].getSequence() + tmp.substring(pos));\r
165       }\r
166 \r
167     }\r
168   }\r
169 \r
170   public SequenceI[] getColumns(int seq1, int seq2, int start, int end) {\r
171     SequenceI[] seqs = new Sequence[(seq2-seq1)+1];\r
172     for (int i=seq1; i<= seq2; i++ ) {\r
173       seqs[i] = new Sequence(getSequenceAt(i).getName(),\r
174                              getSequenceAt(i).getSequence().substring(start,end),\r
175                              getSequenceAt(i).findPosition(start),\r
176                              getSequenceAt(i).findPosition(end));\r
177     }\r
178     return seqs;\r
179   }\r
180 \r
181   public void trimLeft(int i) {\r
182     for (int j = 0;j< getHeight();j++) {\r
183 \r
184       SequenceI s        = getSequenceAt(j);\r
185       int       newstart = s.findPosition(i);\r
186 \r
187       s.setStart(newstart);\r
188       s.setSequence(s.getSequence().substring(i));\r
189 \r
190     }\r
191   }\r
192 \r
193   public void  trimRight(int i) {\r
194     for (int j = 0;j< getHeight();j++) {\r
195       SequenceI s      = getSequenceAt(j);\r
196       int       newend = s.findPosition(i);\r
197 \r
198       s.setEnd(newend);\r
199       s.setSequence(s.getSequence().substring(0,i+1));\r
200     }\r
201   }\r
202 \r
203   public void deleteSequence(SequenceI s)\r
204   {\r
205     for (int i=0; i < getHeight(); i++)\r
206       if (getSequenceAt(i) == s)\r
207         deleteSequence(i);\r
208   }\r
209 \r
210   public void  deleteSequence(int i)\r
211   {\r
212     sequences.removeElementAt(i);\r
213   }\r
214 \r
215 \r
216   public Vector removeRedundancy(float threshold, Vector sel) {\r
217     Vector del = new Vector();\r
218 \r
219     for (int i = 1; i < sel.size(); i++)\r
220     {\r
221       for (int j = 0; j < i; j++)\r
222       {\r
223         // Only do the comparison if either have not been deleted\r
224         if (!del.contains( (SequenceI) sel.elementAt(i)) ||\r
225             !del.contains( (SequenceI) sel.elementAt(j)))\r
226         {\r
227 \r
228           float pid = Comparison.compare( (SequenceI) sel.elementAt(j),\r
229                                          (SequenceI) sel.elementAt(i));\r
230 \r
231           if (pid >= threshold)\r
232           {\r
233             // Delete the shortest one\r
234             if ( ( (SequenceI) sel.elementAt(j)).getSequence().length() >\r
235                 ( (SequenceI) sel.elementAt(i)).getSequence().length())\r
236               del.addElement(sel.elementAt(i));\r
237             else\r
238               del.addElement(sel.elementAt(i));\r
239           }\r
240         }\r
241       }\r
242     }\r
243 \r
244     // Now delete the sequences\r
245     for (int i=0; i < del.size(); i++)\r
246       deleteSequence((SequenceI)del.elementAt(i));\r
247 \r
248     return del;\r
249   }\r
250 \r
251   public void sortByPID(SequenceI s) {\r
252 \r
253     float     scores[] = new float[getHeight()];\r
254     SequenceI seqs[]   = new SequenceI[getHeight()];\r
255 \r
256     for (int i = 0; i < getHeight(); i++) {\r
257       scores[i] = Comparison.compare(getSequenceAt(i),s);\r
258       seqs[i]   = getSequenceAt(i);\r
259     }\r
260 \r
261     QuickSort.sort(scores,0,scores.length-1,seqs);\r
262 \r
263     int len = 0;\r
264 \r
265     if (getHeight()%2 == 0) {\r
266       len = getHeight()/2;\r
267     } else {\r
268       len = (getHeight()+1)/2;\r
269     }\r
270 \r
271     for (int i = 0; i < len; i++) {\r
272       SequenceI tmp = seqs[i];\r
273       sequences.setElementAt(seqs[getHeight()-i-1],i);\r
274       sequences.setElementAt(tmp,getHeight()-i-1);\r
275     }\r
276   }\r
277 \r
278   public void sortByID() {\r
279     String    ids[]   = new String[getHeight()];\r
280     SequenceI seqs[]  = new SequenceI[getHeight()];\r
281 \r
282     for (int i = 0; i < getHeight(); i++) {\r
283       ids[i]  = getSequenceAt(i).getName();\r
284       seqs[i] = getSequenceAt(i);\r
285     }\r
286 \r
287     QuickSort.sort(ids,seqs);\r
288 \r
289     int len = 0;\r
290 \r
291     if (getHeight()%2 == 0) {\r
292       len = getHeight()/2;\r
293     } else {\r
294       len = (getHeight()+1)/2;\r
295       System.out.println("Sort len is odd = " + len);\r
296     }\r
297     for (int i = 0; i < len; i++) {\r
298       System.out.println("Swapping " + seqs[i].getName() + " and " + seqs[getHeight()-i-1].getName());\r
299       SequenceI tmp = seqs[i];\r
300       sequences.setElementAt(seqs[getHeight()-i-1],i);\r
301       sequences.setElementAt(tmp,getHeight()-i-1);\r
302     }\r
303   }\r
304 \r
305   /**    */\r
306   public SequenceGroup findGroup(int i) {\r
307     return findGroup(getSequenceAt(i));\r
308   }\r
309 \r
310   /**    */\r
311   public SequenceGroup findGroup(SequenceI s) {\r
312     for (int i = 0; i < this.groups.size();i++)\r
313     {\r
314       SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
315       if (sg.sequences.contains(s))\r
316         return sg;\r
317 \r
318     }\r
319     return null;\r
320   }\r
321 \r
322   public SequenceGroup [] findAllGroups(SequenceI s)\r
323   {\r
324 \r
325     Vector temp = new Vector();\r
326 \r
327     for (int i = 0; i < this.groups.size();i++)\r
328     {\r
329       SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
330 \r
331       if (sg.sequences.contains(s))\r
332        temp.addElement(sg);\r
333     }\r
334 \r
335     SequenceGroup [] ret = new SequenceGroup[temp.size()];\r
336     for(int i=0; i<temp.size(); i++)\r
337       ret[i] = (SequenceGroup)temp.elementAt(i);\r
338 \r
339     return ret;\r
340 \r
341   }\r
342   /**    */\r
343   public void addToGroup(SequenceGroup g, SequenceI s) {\r
344     if (!(g.sequences.contains(s))) {\r
345       g.sequences.addElement(s);\r
346     }\r
347   }\r
348   /**    */\r
349   public void removeFromGroup(SequenceGroup g,SequenceI s) {\r
350     if (g != null && g.sequences != null) {\r
351       if (g.sequences.contains(s)) {\r
352         g.sequences.removeElement(s);\r
353         if (g.sequences.size() == 0) {\r
354           groups.removeElement(g);\r
355         }\r
356       }\r
357     }\r
358   }\r
359 \r
360   public void addSuperGroup(SuperGroup sg)\r
361   {\r
362     superGroup.addElement(sg);\r
363   }\r
364 \r
365   public void removeSuperGroup(SuperGroup sg)\r
366   {\r
367     superGroup.removeElement(sg);\r
368   }\r
369 \r
370   public SuperGroup     getSuperGroup(SequenceGroup sg)\r
371   {\r
372     for (int i = 0; i < this.superGroup.size(); i++)\r
373     {\r
374       SuperGroup temp = (SuperGroup) superGroup.elementAt(i);\r
375       if (temp.sequenceGroups.contains(sg))\r
376         return temp;\r
377     }\r
378     return null;\r
379   }\r
380 \r
381   /**    */\r
382   public void addGroup(SequenceGroup sg) {\r
383     if(!groups.contains(sg))\r
384       groups.addElement(sg);\r
385   }\r
386 \r
387   public void deleteAllGroups()\r
388   {\r
389     groups.removeAllElements();\r
390     superGroup.removeAllElements();\r
391    int i=0;\r
392     while (i < sequences.size()) {\r
393      SequenceI s = getSequenceAt(i);\r
394      s.setColor(java.awt.Color.white);\r
395      i++;\r
396    }\r
397 \r
398 \r
399   }\r
400 \r
401   /**    */\r
402   public void deleteGroup(SequenceGroup g) {\r
403     if (groups.contains(g)) {\r
404       groups.removeElement(g);\r
405     }\r
406   }\r
407 \r
408   /**    */\r
409   public SequenceI findName(String name) {\r
410     int i = 0;\r
411     while (i < sequences.size()) {\r
412       SequenceI s = getSequenceAt(i);\r
413       if (s.getName().equals(name))\r
414         return s;\r
415 \r
416       i++;\r
417     }\r
418     return null;\r
419   }\r
420 \r
421   /**    */\r
422   public SequenceI findbyDisplayId(String name) {\r
423     int i = 0;\r
424     while (i < sequences.size()) {\r
425       SequenceI s = getSequenceAt(i);\r
426       if (s.getDisplayId().equals(name))\r
427         return s;\r
428 \r
429       i++;\r
430     }\r
431     return null;\r
432   }\r
433 \r
434   /**    */\r
435   public int findIndex(SequenceI s)\r
436   {\r
437     int i=0;\r
438     while (i < sequences.size())\r
439     {\r
440       if (s == getSequenceAt(i))\r
441         return i;\r
442 \r
443       i++;\r
444     }\r
445     return -1;\r
446   }\r
447 \r
448   public int getHeight() {\r
449     return sequences.size();\r
450   }\r
451 \r
452 \r
453   public int getWidth()\r
454   {\r
455     int maxLength = -1;\r
456     for (int i = 0; i < sequences.size(); i++)\r
457     {\r
458       if (getSequenceAt(i).getLength() > maxLength)\r
459         maxLength = getSequenceAt(i).getLength();\r
460     }\r
461 \r
462     return maxLength;\r
463   }\r
464 \r
465 \r
466   public int getMaxIdLength() {\r
467     int max = 0;\r
468     int i   = 0;\r
469 \r
470     while (i < sequences.size()) {\r
471       SequenceI seq = getSequenceAt(i);\r
472       String    tmp = seq.getName() + "/" + seq.getStart() + "-" + seq.getEnd();\r
473 \r
474       if (tmp.length() > max) {\r
475         max = tmp.length();\r
476       }\r
477 \r
478       i++;\r
479     }\r
480     return max;\r
481   }\r
482 \r
483   public void setGapCharacter(char gc)\r
484   {\r
485     gapCharacter = gc;\r
486     for (int i=0; i < sequences.size(); i++)\r
487      {\r
488        Sequence seq = (Sequence)sequences.elementAt(i);\r
489        seq.sequence = seq.sequence.replace('.', gc);\r
490        seq.sequence = seq.sequence.replace('-', gc);\r
491      }\r
492   }\r
493 \r
494   public char getGapCharacter() {\r
495     return gapCharacter;\r
496   }\r
497 \r
498   public Vector getAAFrequency()\r
499   {\r
500     return AAFrequency.calculate(sequences, 0, getWidth());\r
501   }\r
502 \r
503   public boolean isAligned()\r
504   {\r
505     int width = getWidth();\r
506     for (int i = 0; i < sequences.size(); i++)\r
507       if (getSequenceAt(i).getLength() != width)\r
508         return false;\r
509 \r
510     return true;\r
511   }\r
512 \r
513    public void deleteAnnotation(AlignmentAnnotation aa)\r
514    {\r
515      int aSize = 1;\r
516      if(annotations!=null)\r
517        aSize = annotations.length;\r
518 \r
519      AlignmentAnnotation [] temp = new AlignmentAnnotation [aSize-1];\r
520 \r
521      int tIndex = 0;\r
522      for (int i = 0; i < aSize; i++)\r
523       {\r
524         if(annotations[i]==aa)\r
525           continue;\r
526 \r
527 \r
528         temp[tIndex] = annotations[i];\r
529         tIndex++;\r
530       }\r
531 \r
532      annotations = temp;\r
533 \r
534    }\r
535 \r
536   public void addAnnotation(AlignmentAnnotation aa)\r
537   {\r
538     int aSize = 1;\r
539     if(annotations!=null)\r
540       aSize = annotations.length+1;\r
541 \r
542     AlignmentAnnotation [] temp = new AlignmentAnnotation [aSize];\r
543     int i=0;\r
544     if (aSize > 1)\r
545       for (i = 0; i < aSize-1; i++)\r
546         temp[i] = annotations[i];\r
547 \r
548     temp[i] = aa;\r
549 \r
550     annotations = temp;\r
551   }\r
552   public AlignmentAnnotation[] getAlignmentAnnotation()\r
553   {\r
554     return annotations;\r
555   }\r
556 \r
557 }\r
558 \r
559 \r
560 \r
561 \r
562 \r
563 \r
564 \r
565 \r