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