Alignment Annotation added
[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 ArrayList   superGroup = new ArrayList();\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     ArrayList temp = new ArrayList();\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.add(sg);\r
333     }\r
334 \r
335     SequenceGroup [] ret = new SequenceGroup[temp.size()];\r
336     temp.toArray( ret );\r
337 \r
338     return ret;\r
339 \r
340   }\r
341   /**    */\r
342   public void addToGroup(SequenceGroup g, SequenceI s) {\r
343     if (!(g.sequences.contains(s))) {\r
344       g.sequences.addElement(s);\r
345     }\r
346   }\r
347   /**    */\r
348   public void removeFromGroup(SequenceGroup g,SequenceI s) {\r
349     if (g != null && g.sequences != null) {\r
350       if (g.sequences.contains(s)) {\r
351         g.sequences.removeElement(s);\r
352         if (g.sequences.size() == 0) {\r
353           groups.removeElement(g);\r
354         }\r
355       }\r
356     }\r
357   }\r
358 \r
359   public void addSuperGroup(SuperGroup sg)\r
360   {\r
361     superGroup.add(sg);\r
362   }\r
363 \r
364   public void removeSuperGroup(SuperGroup sg)\r
365   {\r
366     superGroup.remove(sg);\r
367   }\r
368 \r
369   public SuperGroup     getSuperGroup(SequenceGroup sg)\r
370   {\r
371     for (int i = 0; i < this.superGroup.size(); i++)\r
372     {\r
373       SuperGroup temp = (SuperGroup) superGroup.get(i);\r
374       if (temp.sequenceGroups.contains(sg))\r
375         return temp;\r
376     }\r
377     return null;\r
378   }\r
379 \r
380   /**    */\r
381   public void addGroup(SequenceGroup sg) {\r
382     if(!groups.contains(sg))\r
383       groups.addElement(sg);\r
384   }\r
385 \r
386   public void deleteAllGroups()\r
387   {\r
388     groups.clear();\r
389     superGroup.clear();\r
390    int i=0;\r
391     while (i < sequences.size()) {\r
392      SequenceI s = getSequenceAt(i);\r
393      s.setColor(java.awt.Color.white);\r
394      i++;\r
395    }\r
396 \r
397 \r
398   }\r
399 \r
400   /**    */\r
401   public void deleteGroup(SequenceGroup g) {\r
402     if (groups.contains(g)) {\r
403       groups.removeElement(g);\r
404     }\r
405   }\r
406 \r
407   /**    */\r
408   public SequenceI findName(String name) {\r
409     int i = 0;\r
410     while (i < sequences.size()) {\r
411       SequenceI s = getSequenceAt(i);\r
412       if (s.getName().equals(name))\r
413         return s;\r
414 \r
415       i++;\r
416     }\r
417     return null;\r
418   }\r
419 \r
420   /**    */\r
421   public SequenceI findbyDisplayId(String name) {\r
422     int i = 0;\r
423     while (i < sequences.size()) {\r
424       SequenceI s = getSequenceAt(i);\r
425       if (s.getDisplayId().equals(name))\r
426         return s;\r
427 \r
428       i++;\r
429     }\r
430     return null;\r
431   }\r
432 \r
433   /**    */\r
434   public int findIndex(SequenceI s)\r
435   {\r
436     int i=0;\r
437     while (i < sequences.size())\r
438     {\r
439       if (s == getSequenceAt(i))\r
440         return i;\r
441 \r
442       i++;\r
443     }\r
444     return -1;\r
445   }\r
446 \r
447   public int getHeight() {\r
448     return sequences.size();\r
449   }\r
450 \r
451 \r
452   public int getWidth()\r
453   {\r
454     int maxLength = -1;\r
455     for (int i = 0; i < sequences.size(); i++)\r
456     {\r
457       if (getSequenceAt(i).getLength() > maxLength)\r
458         maxLength = getSequenceAt(i).getLength();\r
459     }\r
460 \r
461     return maxLength;\r
462   }\r
463 \r
464 \r
465   public int getMaxIdLength() {\r
466     int max = 0;\r
467     int i   = 0;\r
468 \r
469     while (i < sequences.size()) {\r
470       SequenceI seq = getSequenceAt(i);\r
471       String    tmp = seq.getName() + "/" + seq.getStart() + "-" + seq.getEnd();\r
472 \r
473       if (tmp.length() > max) {\r
474         max = tmp.length();\r
475       }\r
476 \r
477       i++;\r
478     }\r
479     return max;\r
480   }\r
481 \r
482   public void setGapCharacter(char gc)\r
483   {\r
484     char old = getGapCharacter();\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(old, gc);\r
490      }\r
491   }\r
492 \r
493   public char getGapCharacter() {\r
494     return gapCharacter;\r
495   }\r
496 \r
497   public Vector getAAFrequency()\r
498   {\r
499     return AAFrequency.calculate(sequences, 0, getWidth());\r
500   }\r
501 \r
502   public boolean isAligned()\r
503   {\r
504     int width = getWidth();\r
505     for (int i = 0; i < sequences.size(); i++)\r
506       if (getSequenceAt(i).getLength() != width)\r
507         return false;\r
508 \r
509     return true;\r
510   }\r
511 \r
512    public void deleteAnnotation(AlignmentAnnotation aa)\r
513    {\r
514      int aSize = 1;\r
515      if(annotations!=null)\r
516        aSize = annotations.length;\r
517 \r
518      AlignmentAnnotation [] temp = new AlignmentAnnotation [aSize-1];\r
519 \r
520      int tIndex = 0;\r
521      for (int i = 0; i < aSize; i++)\r
522       {\r
523         if(annotations[i]==aa)\r
524           continue;\r
525 \r
526 \r
527         temp[tIndex] = annotations[i];\r
528         tIndex++;\r
529       }\r
530 \r
531      annotations = temp;\r
532 \r
533    }\r
534 \r
535   public void addAnnotation(AlignmentAnnotation aa)\r
536   {\r
537     int aSize = 1;\r
538     if(annotations!=null)\r
539       aSize = annotations.length+1;\r
540 \r
541     AlignmentAnnotation [] temp = new AlignmentAnnotation [aSize];\r
542     int i=0;\r
543     if (aSize > 1)\r
544       for (i = 0; i < aSize-1; i++)\r
545         temp[i] = annotations[i];\r
546 \r
547     temp[i] = aa;\r
548 \r
549     annotations = temp;\r
550   }\r
551   public AlignmentAnnotation[] getAlignmentAnnotation()\r
552   {\r
553     return annotations;\r
554   }\r
555 \r
556 }\r
557 \r
558 \r
559 \r
560 \r
561 \r
562 \r
563 \r
564 \r