Set gap chararcter replaces all existing gap chars
[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   public    Hashtable[] cons;\r
15   protected char      gapCharacter = '.';\r
16 \r
17   /** Make an alignment from an array of Sequences.\r
18   *\r
19   * @param sequences\r
20   */\r
21   public Alignment(SequenceI[] seqs) {\r
22     sequences = new Vector();\r
23 \r
24     for (int i=0; i < seqs.length; i++)\r
25       sequences.addElement(seqs[i]);\r
26 \r
27     SequenceGroup all = new SequenceGroup();\r
28     all.setName("Group 1");\r
29     groups.addElement(all);\r
30 \r
31     int i = 0;\r
32 \r
33     while (i < seqs.length) {\r
34       addToGroup(all,seqs[i]);\r
35       i++;\r
36     }\r
37 \r
38     getWidth();\r
39   }\r
40 \r
41   public Vector      getSequences() {\r
42     return sequences;\r
43   }\r
44 \r
45   public SequenceI getSequenceAt(int i) {\r
46     if (i < sequences.size()) {\r
47       return (SequenceI)sequences.elementAt(i);\r
48     }\r
49 \r
50     return null;\r
51   }\r
52 \r
53   /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
54    * Should put the new sequence in a sequence group!!!\r
55    *\r
56    * @param snew\r
57    */\r
58   public void addSequence(SequenceI snew) {\r
59     sequences.addElement(snew);\r
60 \r
61     ((SequenceGroup)groups.lastElement()).addSequence(snew);\r
62   }\r
63 \r
64   public void addSequence(SequenceI[] seq) {\r
65     for (int i=0; i < seq.length; i++) {\r
66       addSequence(seq[i]);\r
67     }\r
68   }\r
69 \r
70   /** Adds a sequence to the alignment.  Recalculates maxLength and size.\r
71    * Should put the new sequence in a sequence group!!!\r
72    *\r
73    * @param snew\r
74    */\r
75   public void setSequenceAt(int i,SequenceI snew) {\r
76     SequenceI oldseq = getSequenceAt(i);\r
77     deleteSequence(oldseq);\r
78 \r
79     sequences.setElementAt(snew,i);\r
80 \r
81     ((SequenceGroup)groups.lastElement()).addSequence(snew);\r
82   }\r
83 \r
84   public Vector getGroups() {\r
85     return groups;\r
86   }\r
87 \r
88   /** Sorts the sequences by sequence group size - largest to smallest.\r
89    * Uses QuickSort.\r
90    */\r
91   public void sortGroups() {\r
92     float[]  arr = new float [groups.size()];\r
93     Object[] s   = new Object[groups.size()];\r
94 \r
95     for (int i=0; i < groups.size(); i++) {\r
96       arr[i] = ((SequenceGroup)groups.elementAt(i)).sequences.size();\r
97       s[i]   = groups.elementAt(i);\r
98     }\r
99 \r
100     QuickSort.sort(arr,s);\r
101 \r
102     Vector newg = new Vector(groups.size());\r
103 \r
104     for (int i=groups.size()-1; i >= 0; i--) {\r
105       newg.addElement(s[i]);\r
106     }\r
107 \r
108     groups = newg;\r
109   }\r
110 \r
111   /** Takes out columns consisting entirely of gaps (-,.," ")\r
112    */\r
113   public void removeGaps()\r
114   {\r
115 \r
116     SequenceI current;\r
117     int iSize = getWidth();\r
118     for (int i=0; i < iSize; i++)\r
119     {\r
120       boolean delete = true;\r
121       for (int j=0; j < getHeight(); j++)\r
122       {\r
123         current = getSequenceAt(j);\r
124         if (current.getLength() > i)\r
125         {\r
126             /* MC Should move this to a method somewhere */\r
127           if (current.getCharAt(i)!='-' && current.getCharAt(i)!='.' && current.getCharAt(i)!=' ')\r
128             delete = false;\r
129 \r
130         }\r
131       }\r
132 \r
133       if ( delete )\r
134       {\r
135         deleteColumns(i,i);\r
136         iSize--;\r
137         i--;\r
138       }\r
139     }\r
140 \r
141 \r
142   }\r
143 \r
144   /** Returns an array of Sequences containing columns\r
145    * start to end (inclusive) only.\r
146    *\r
147    * @param start start column to fetch\r
148    * @param end end column to fetch\r
149    * @return Array of Sequences, ready to put into a new Alignment\r
150    */\r
151   public SequenceI[] getColumns(int start, int end) {\r
152     return getColumns(0,getHeight()-1,start,end);\r
153   }\r
154 \r
155   /** Removes a range of columns (start to end inclusive).\r
156    *\r
157    * @param start Start column in the alignment\r
158    * @param end End column in the alignment\r
159    */\r
160   public void deleteColumns(int start, int end) {\r
161     deleteColumns(0,getHeight()-1,start,end);\r
162   }\r
163 \r
164   public void deleteColumns(int seq1, int seq2, int start, int end) {\r
165 \r
166     for (int i=0; i <= (end-start); i++) {\r
167       for (int j=seq1; j <= seq2; j++) {\r
168         getSequenceAt(j).deleteCharAt(start);\r
169       }\r
170     }\r
171   }\r
172 \r
173   public void insertColumns(SequenceI[] seqs, int pos) {\r
174     if (seqs.length == getHeight()) {\r
175       for (int i=0; i < getHeight();i++) {\r
176         String tmp = new String(getSequenceAt(i).getSequence());\r
177         getSequenceAt(i).setSequence(tmp.substring(0,pos) + seqs[i].getSequence() + tmp.substring(pos));\r
178       }\r
179 \r
180     }\r
181   }\r
182 \r
183   public SequenceI[] getColumns(int seq1, int seq2, int start, int end) {\r
184     SequenceI[] seqs = new Sequence[(seq2-seq1)+1];\r
185     for (int i=seq1; i<= seq2; i++ ) {\r
186       seqs[i] = new Sequence(getSequenceAt(i).getName(),\r
187                              getSequenceAt(i).getSequence().substring(start,end),\r
188                              getSequenceAt(i).findPosition(start),\r
189                              getSequenceAt(i).findPosition(end));\r
190     }\r
191     return seqs;\r
192   }\r
193 \r
194   public void trimLeft(int i) {\r
195     for (int j = 0;j< getHeight();j++) {\r
196 \r
197       SequenceI s        = getSequenceAt(j);\r
198       int       newstart = s.findPosition(i);\r
199 \r
200       s.setStart(newstart);\r
201       s.setSequence(s.getSequence().substring(i));\r
202 \r
203     }\r
204   }\r
205 \r
206   public void  trimRight(int i) {\r
207     for (int j = 0;j< getHeight();j++) {\r
208       SequenceI s      = getSequenceAt(j);\r
209       int       newend = s.findPosition(i);\r
210 \r
211       s.setEnd(newend);\r
212       s.setSequence(s.getSequence().substring(0,i+1));\r
213     }\r
214   }\r
215 \r
216   public void deleteSequence(SequenceI s)\r
217   {\r
218     for (int i=0; i < getHeight(); i++)\r
219       if (getSequenceAt(i) == s)\r
220         deleteSequence(i);\r
221   }\r
222 \r
223   public void  deleteSequence(int i)\r
224   {\r
225     sequences.removeElementAt(i);\r
226   }\r
227 \r
228 \r
229   public Vector removeRedundancy(float threshold, Vector sel) {\r
230     Vector del = new Vector();\r
231 \r
232     for (int i=1; i < sel.size(); i++) {\r
233       for (int j = 0; j < i; j++) {\r
234         // Only do the comparison if either have not been deleted\r
235         if (!del.contains((SequenceI)sel.elementAt(i)) ||\r
236             !del.contains((SequenceI)sel.elementAt(j))) {\r
237 \r
238           float pid = Comparison.compare((SequenceI)sel.elementAt(j),\r
239                                          (SequenceI)sel.elementAt(i));\r
240 \r
241           if (pid >= threshold) {\r
242             // Delete the shortest one\r
243             if (((SequenceI)sel.elementAt(j)).getSequence().length() >\r
244                 ((SequenceI)sel.elementAt(i)).getSequence().length()) {\r
245               del.addElement(sel.elementAt(i));\r
246               System.out.println("Deleting sequence " + ((SequenceI)sel.elementAt(i)).getName());\r
247             } else {\r
248               del.addElement(sel.elementAt(i));\r
249               System.out.println("Deleting sequence " + ((SequenceI)sel.elementAt(i)).getName());\r
250             }\r
251           }\r
252         }\r
253       }\r
254     }\r
255 \r
256     // Now delete the sequences\r
257     for (int i=0; i < del.size(); i++) {\r
258       System.out.println("Deleting sequence " + ((SequenceI)del.elementAt(i)).getName());\r
259       deleteSequence((SequenceI)del.elementAt(i));\r
260     }\r
261 \r
262     return del;\r
263   }\r
264 \r
265   public void sortByPID(SequenceI s) {\r
266 \r
267     float     scores[] = new float[getHeight()];\r
268     SequenceI seqs[]   = new SequenceI[getHeight()];\r
269 \r
270     for (int i = 0; i < getHeight(); i++) {\r
271       scores[i] = Comparison.compare(getSequenceAt(i),s);\r
272       seqs[i]   = getSequenceAt(i);\r
273     }\r
274 \r
275     QuickSort.sort(scores,0,scores.length-1,seqs);\r
276 \r
277     int len = 0;\r
278 \r
279     if (getHeight()%2 == 0) {\r
280       len = getHeight()/2;\r
281     } else {\r
282       len = (getHeight()+1)/2;\r
283     }\r
284 \r
285     for (int i = 0; i < len; i++) {\r
286       SequenceI tmp = seqs[i];\r
287       sequences.setElementAt(seqs[getHeight()-i-1],i);\r
288       sequences.setElementAt(tmp,getHeight()-i-1);\r
289     }\r
290   }\r
291 \r
292   public void sortByID() {\r
293     String    ids[]   = new String[getHeight()];\r
294     SequenceI seqs[]  = new SequenceI[getHeight()];\r
295 \r
296     for (int i = 0; i < getHeight(); i++) {\r
297       ids[i]  = getSequenceAt(i).getName();\r
298       seqs[i] = getSequenceAt(i);\r
299     }\r
300 \r
301     QuickSort.sort(ids,seqs);\r
302 \r
303     int len = 0;\r
304 \r
305     if (getHeight()%2 == 0) {\r
306       len = getHeight()/2;\r
307     } else {\r
308       len = (getHeight()+1)/2;\r
309       System.out.println("Sort len is odd = " + len);\r
310     }\r
311     for (int i = 0; i < len; i++) {\r
312       System.out.println("Swapping " + seqs[i].getName() + " and " + seqs[getHeight()-i-1].getName());\r
313       SequenceI tmp = seqs[i];\r
314       sequences.setElementAt(seqs[getHeight()-i-1],i);\r
315       sequences.setElementAt(tmp,getHeight()-i-1);\r
316     }\r
317   }\r
318 \r
319   /**    */\r
320   public SequenceGroup findGroup(int i) {\r
321     return findGroup(getSequenceAt(i));\r
322   }\r
323 \r
324   /**    */\r
325   public SequenceGroup findGroup(SequenceI s) {\r
326     for (int i = 0; i < this.groups.size();i++)\r
327     {\r
328       SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
329       if (sg.sequences.contains(s))\r
330         return sg;\r
331 \r
332     }\r
333     return null;\r
334 \r
335   }\r
336   /**    */\r
337   public void addToGroup(SequenceGroup g, SequenceI s) {\r
338     if (!(g.sequences.contains(s))) {\r
339       g.sequences.addElement(s);\r
340     }\r
341   }\r
342   /**    */\r
343   public void removeFromGroup(SequenceGroup g,SequenceI s) {\r
344     if (g != null && g.sequences != null) {\r
345       if (g.sequences.contains(s)) {\r
346         g.sequences.removeElement(s);\r
347         if (g.sequences.size() == 0) {\r
348           groups.removeElement(g);\r
349         }\r
350       }\r
351     }\r
352   }\r
353 \r
354   /**    */\r
355   public void addGroup(SequenceGroup sg) {\r
356     groups.addElement(sg);\r
357   }\r
358 \r
359   /**    */\r
360   public SequenceGroup addGroup() {\r
361     SequenceGroup sg = new SequenceGroup();\r
362     groups.addElement(sg);\r
363     return sg;\r
364   }\r
365 \r
366   /**    */\r
367   public void deleteGroup(SequenceGroup g) {\r
368     if (groups.contains(g)) {\r
369       groups.removeElement(g);\r
370     }\r
371   }\r
372 \r
373   /**    */\r
374   public SequenceI findName(String name) {\r
375     int i = 0;\r
376     while (i < sequences.size()) {\r
377       SequenceI s = getSequenceAt(i);\r
378       if (s.getName().equals(name))\r
379         return s;\r
380 \r
381       i++;\r
382     }\r
383     return null;\r
384   }\r
385 \r
386   /**    */\r
387   public SequenceI findbyDisplayId(String name) {\r
388     int i = 0;\r
389     while (i < sequences.size()) {\r
390       SequenceI s = getSequenceAt(i);\r
391       if (s.getDisplayId().equals(name))\r
392         return s;\r
393 \r
394       i++;\r
395     }\r
396     return null;\r
397   }\r
398 \r
399   /**    */\r
400   public int findIndex(SequenceI s) {\r
401     int i=0;\r
402     while (i < sequences.size()) {\r
403       if (s == getSequenceAt(i)) {\r
404         return i;\r
405       }\r
406       i++;\r
407     }\r
408     return -1;\r
409   }\r
410 \r
411   public int getHeight() {\r
412     return sequences.size();\r
413   }\r
414 \r
415 \r
416   public int getWidth()\r
417   {\r
418     int maxLength = -1;\r
419     for (int i = 0; i < sequences.size(); i++)\r
420     {\r
421       if (getSequenceAt(i).getLength() > maxLength)\r
422         maxLength = getSequenceAt(i).getLength();\r
423     }\r
424 \r
425     return maxLength;\r
426   }\r
427 \r
428 \r
429   public int getMaxIdLength() {\r
430     int max = 0;\r
431     int i   = 0;\r
432 \r
433     while (i < sequences.size()) {\r
434       SequenceI seq = getSequenceAt(i);\r
435       String    tmp = seq.getName() + "/" + seq.getStart() + "-" + seq.getEnd();\r
436 \r
437       if (tmp.length() > max) {\r
438         max = tmp.length();\r
439       }\r
440 \r
441       i++;\r
442     }\r
443     return max;\r
444   }\r
445 \r
446   public void setGapCharacter(char gc)\r
447   {\r
448     char old = getGapCharacter();\r
449     gapCharacter = gc;\r
450     for (int i=0; i < sequences.size(); i++)\r
451      {\r
452        Sequence seq = (Sequence)sequences.elementAt(i);\r
453        seq.sequence = seq.sequence.replace(old, gc);\r
454      }\r
455   }\r
456 \r
457   public char getGapCharacter() {\r
458     return gapCharacter;\r
459   }\r
460 \r
461   public Vector getAAFrequency()\r
462   {\r
463     return AAFrequency.calculate(sequences, 0, getWidth());\r
464   }\r
465 }\r
466 \r
467 \r
468 \r
469 \r
470 \r
471 \r
472 \r
473 \r