conservation removed
[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 \r
18   public boolean featuresAdded = false;\r
19 \r
20   /** Make an alignment from an array of Sequences.\r
21   *\r
22   * @param sequences\r
23   */\r
24   public Alignment(SequenceI[] seqs) {\r
25     sequences = new Vector();\r
26 \r
27     for (int i=0; i < seqs.length; i++)\r
28       sequences.addElement(seqs[i]);\r
29 \r
30     getWidth();\r
31   }\r
32 \r
33   public Vector      getSequences() {\r
34     return sequences;\r
35   }\r
36 \r
37   public SequenceI getSequenceAt(int i) {\r
38     if (i < sequences.size()) {\r
39       return (SequenceI)sequences.elementAt(i);\r
40     }\r
41 \r
42     return null;\r
43   }\r
44 \r
45   /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
46    *\r
47    * @param snew\r
48    */\r
49   public void addSequence(SequenceI snew) {\r
50     sequences.addElement(snew);\r
51   }\r
52 \r
53   public void addSequence(SequenceI[] seq) {\r
54     for (int i=0; i < seq.length; i++) {\r
55       addSequence(seq[i]);\r
56     }\r
57   }\r
58 \r
59   /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
60     *\r
61    * @param snew\r
62    */\r
63   public void setSequenceAt(int i,SequenceI snew) {\r
64     SequenceI oldseq = getSequenceAt(i);\r
65     deleteSequence(oldseq);\r
66 \r
67     sequences.setElementAt(snew,i);\r
68   }\r
69 \r
70   public Vector getGroups() {\r
71     return groups;\r
72   }\r
73 \r
74   /** Sorts the sequences by sequence group size - largest to smallest.\r
75    * Uses QuickSort.\r
76    */\r
77   public void sortGroups() {\r
78     float[]  arr = new float [groups.size()];\r
79     Object[] s   = new Object[groups.size()];\r
80 \r
81     for (int i=0; i < groups.size(); i++) {\r
82       arr[i] = ((SequenceGroup)groups.elementAt(i)).sequences.size();\r
83       s[i]   = groups.elementAt(i);\r
84     }\r
85 \r
86     QuickSort.sort(arr,s);\r
87 \r
88     Vector newg = new Vector(groups.size());\r
89 \r
90     for (int i=groups.size()-1; i >= 0; i--) {\r
91       newg.addElement(s[i]);\r
92     }\r
93 \r
94     groups = newg;\r
95   }\r
96 \r
97   /** Takes out columns consisting entirely of gaps (-,.," ")\r
98    */\r
99   public void removeGaps()\r
100   {\r
101 \r
102     SequenceI current;\r
103     int iSize = getWidth();\r
104     for (int i=0; i < iSize; i++)\r
105     {\r
106       boolean delete = true;\r
107       for (int j=0; j < getHeight(); j++)\r
108       {\r
109         current = getSequenceAt(j);\r
110         if (current.getLength() > i)\r
111         {\r
112             /* MC Should move this to a method somewhere */\r
113           if ( !jalview.util.Comparison.isGap(current.getCharAt(i)))\r
114             delete = false;\r
115 \r
116         }\r
117       }\r
118 \r
119       if ( delete )\r
120       {\r
121         deleteColumns(i,i);\r
122         iSize--;\r
123         i--;\r
124       }\r
125     }\r
126 \r
127 \r
128   }\r
129 \r
130   /** Returns an array of Sequences containing columns\r
131    * start to end (inclusive) only.\r
132    *\r
133    * @param start start column to fetch\r
134    * @param end end column to fetch\r
135    * @return Array of Sequences, ready to put into a new Alignment\r
136    */\r
137   public SequenceI[] getColumns(int start, int end) {\r
138     return getColumns(0,getHeight()-1,start,end);\r
139   }\r
140 \r
141   /** Removes a range of columns (start to end inclusive).\r
142    *\r
143    * @param start Start column in the alignment\r
144    * @param end End column in the alignment\r
145    */\r
146   public void deleteColumns(int start, int end) {\r
147     deleteColumns(0,getHeight()-1,start,end);\r
148   }\r
149 \r
150   public void deleteColumns(int seq1, int seq2, int start, int end) {\r
151 \r
152     for (int i=0; i <= (end-start); i++) {\r
153       for (int j=seq1; j <= seq2; j++) {\r
154         getSequenceAt(j).deleteCharAt(start);\r
155       }\r
156     }\r
157   }\r
158 \r
159   public void insertColumns(SequenceI[] seqs, int pos) {\r
160     if (seqs.length == getHeight()) {\r
161       for (int i=0; i < getHeight();i++) {\r
162         String tmp = new String(getSequenceAt(i).getSequence());\r
163         getSequenceAt(i).setSequence(tmp.substring(0,pos) + seqs[i].getSequence() + tmp.substring(pos));\r
164       }\r
165 \r
166     }\r
167   }\r
168 \r
169   public SequenceI[] getColumns(int seq1, int seq2, int start, int end) {\r
170     SequenceI[] seqs = new Sequence[(seq2-seq1)+1];\r
171     for (int i=seq1; i<= seq2; i++ ) {\r
172       seqs[i] = new Sequence(getSequenceAt(i).getName(),\r
173                              getSequenceAt(i).getSequence().substring(start,end),\r
174                              getSequenceAt(i).findPosition(start),\r
175                              getSequenceAt(i).findPosition(end));\r
176     }\r
177     return seqs;\r
178   }\r
179 \r
180   public void trimLeft(int i) {\r
181     for (int j = 0;j< getHeight();j++) {\r
182 \r
183       SequenceI s        = getSequenceAt(j);\r
184       int       newstart = s.findPosition(i);\r
185 \r
186       s.setStart(newstart);\r
187       s.setSequence(s.getSequence().substring(i));\r
188 \r
189     }\r
190   }\r
191 \r
192   public void  trimRight(int i) {\r
193     for (int j = 0;j< getHeight();j++) {\r
194       SequenceI s      = getSequenceAt(j);\r
195       int       newend = s.findPosition(i);\r
196 \r
197       s.setEnd(newend);\r
198       s.setSequence(s.getSequence().substring(0,i+1));\r
199     }\r
200   }\r
201 \r
202   public void deleteSequence(SequenceI s)\r
203   {\r
204     for (int i=0; i < getHeight(); i++)\r
205       if (getSequenceAt(i) == s)\r
206         deleteSequence(i);\r
207   }\r
208 \r
209   public void  deleteSequence(int i)\r
210   {\r
211     sequences.removeElementAt(i);\r
212   }\r
213 \r
214 \r
215   public Vector removeRedundancy(float threshold, Vector sel) {\r
216     Vector del = new Vector();\r
217 \r
218     for (int i = 1; i < sel.size(); i++)\r
219     {\r
220       for (int j = 0; j < i; j++)\r
221       {\r
222         // Only do the comparison if either have not been deleted\r
223         if (!del.contains( (SequenceI) sel.elementAt(i)) ||\r
224             !del.contains( (SequenceI) sel.elementAt(j)))\r
225         {\r
226 \r
227           float pid = Comparison.compare( (SequenceI) sel.elementAt(j),\r
228                                          (SequenceI) sel.elementAt(i));\r
229 \r
230           if (pid >= threshold)\r
231           {\r
232             // Delete the shortest one\r
233             if ( ( (SequenceI) sel.elementAt(j)).getSequence().length() >\r
234                 ( (SequenceI) sel.elementAt(i)).getSequence().length())\r
235               del.addElement(sel.elementAt(i));\r
236             else\r
237               del.addElement(sel.elementAt(i));\r
238           }\r
239         }\r
240       }\r
241     }\r
242 \r
243     // Now delete the sequences\r
244     for (int i=0; i < del.size(); i++)\r
245       deleteSequence((SequenceI)del.elementAt(i));\r
246 \r
247     return del;\r
248   }\r
249 \r
250   public void sortByPID(SequenceI s) {\r
251 \r
252     float     scores[] = new float[getHeight()];\r
253     SequenceI seqs[]   = new SequenceI[getHeight()];\r
254 \r
255     for (int i = 0; i < getHeight(); i++) {\r
256       scores[i] = Comparison.compare(getSequenceAt(i),s);\r
257       seqs[i]   = getSequenceAt(i);\r
258     }\r
259 \r
260     QuickSort.sort(scores,0,scores.length-1,seqs);\r
261 \r
262     int len = 0;\r
263 \r
264     if (getHeight()%2 == 0) {\r
265       len = getHeight()/2;\r
266     } else {\r
267       len = (getHeight()+1)/2;\r
268     }\r
269 \r
270     for (int i = 0; i < len; i++) {\r
271       SequenceI tmp = seqs[i];\r
272       sequences.setElementAt(seqs[getHeight()-i-1],i);\r
273       sequences.setElementAt(tmp,getHeight()-i-1);\r
274     }\r
275   }\r
276 \r
277   public void sortByID() {\r
278     String    ids[]   = new String[getHeight()];\r
279     SequenceI seqs[]  = new SequenceI[getHeight()];\r
280 \r
281     for (int i = 0; i < getHeight(); i++) {\r
282       ids[i]  = getSequenceAt(i).getName();\r
283       seqs[i] = getSequenceAt(i);\r
284     }\r
285 \r
286     QuickSort.sort(ids,seqs);\r
287 \r
288     int len = 0;\r
289 \r
290     if (getHeight()%2 == 0) {\r
291       len = getHeight()/2;\r
292     } else {\r
293       len = (getHeight()+1)/2;\r
294       System.out.println("Sort len is odd = " + len);\r
295     }\r
296     for (int i = 0; i < len; i++) {\r
297       System.out.println("Swapping " + seqs[i].getName() + " and " + seqs[getHeight()-i-1].getName());\r
298       SequenceI tmp = seqs[i];\r
299       sequences.setElementAt(seqs[getHeight()-i-1],i);\r
300       sequences.setElementAt(tmp,getHeight()-i-1);\r
301     }\r
302   }\r
303 \r
304   /**    */\r
305   public SequenceGroup findGroup(int i) {\r
306     return findGroup(getSequenceAt(i));\r
307   }\r
308 \r
309   /**    */\r
310   public SequenceGroup findGroup(SequenceI s) {\r
311     for (int i = 0; i < this.groups.size();i++)\r
312     {\r
313       SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
314       if (sg.sequences.contains(s))\r
315         return sg;\r
316 \r
317     }\r
318     return null;\r
319   }\r
320 \r
321   public SequenceGroup [] findAllGroups(SequenceI s)\r
322   {\r
323 \r
324     Vector temp = new Vector();\r
325 \r
326     for (int i = 0; i < this.groups.size();i++)\r
327     {\r
328       SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
329 \r
330       if (sg.sequences.contains(s))\r
331        temp.addElement(sg);\r
332     }\r
333 \r
334     SequenceGroup [] ret = new SequenceGroup[temp.size()];\r
335     for(int i=0; i<temp.size(); i++)\r
336       ret[i] = (SequenceGroup)temp.elementAt(i);\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.addElement(sg);\r
362   }\r
363 \r
364   public void removeSuperGroup(SuperGroup sg)\r
365   {\r
366     superGroup.removeElement(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.elementAt(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.removeAllElements();\r
389     superGroup.removeAllElements();\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     gapCharacter = gc;\r
485     for (int i=0; i < sequences.size(); i++)\r
486      {\r
487        Sequence seq = (Sequence)sequences.elementAt(i);\r
488        seq.sequence = seq.sequence.replace('.', gc);\r
489        seq.sequence = seq.sequence.replace('-', 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