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