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