changeCase, removeGaps moved to commands package
[jalview.git] / src / jalview / datamodel / SequenceGroup.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.datamodel;\r
20 \r
21 import jalview.analysis.*;\r
22 \r
23 import jalview.schemes.*;\r
24 \r
25 import java.awt.*;\r
26 \r
27 import java.util.*;\r
28 \r
29 \r
30 /**\r
31  * DOCUMENT ME!\r
32  *\r
33  * @author $author$\r
34  * @version $Revision$\r
35  */\r
36 public class SequenceGroup\r
37 {\r
38     String groupName;\r
39     Conservation conserve;\r
40     Vector aaFrequency;\r
41     boolean displayBoxes;\r
42     boolean displayText;\r
43     boolean colourText;\r
44     private Vector sequences = new Vector();\r
45     int width = -1;\r
46 \r
47     /** DOCUMENT ME!! */\r
48     public ColourSchemeI cs;\r
49     int startRes = 0;\r
50     int endRes = 0;\r
51     Color outlineColour = Color.black;\r
52 \r
53     /**\r
54      * Creates a new SequenceGroup object.\r
55      */\r
56     public SequenceGroup()\r
57     {\r
58         groupName = "Group";\r
59         this.displayBoxes = true;\r
60         this.displayText = true;\r
61         this.colourText = false;\r
62         cs = null;\r
63     }\r
64 \r
65     /**\r
66      * Creates a new SequenceGroup object.\r
67      *\r
68      * @param sequences DOCUMENT ME!\r
69      * @param groupName DOCUMENT ME!\r
70      * @param scheme DOCUMENT ME!\r
71      * @param displayBoxes DOCUMENT ME!\r
72      * @param displayText DOCUMENT ME!\r
73      * @param colourText DOCUMENT ME!\r
74      * @param start DOCUMENT ME!\r
75      * @param end DOCUMENT ME!\r
76      */\r
77     public SequenceGroup(Vector sequences, String groupName,\r
78         ColourSchemeI scheme, boolean displayBoxes, boolean displayText,\r
79         boolean colourText, int start, int end)\r
80     {\r
81         this.sequences = sequences;\r
82         this.groupName = groupName;\r
83         this.displayBoxes = displayBoxes;\r
84         this.displayText = displayText;\r
85         this.colourText = colourText;\r
86         this.cs = scheme;\r
87         startRes = start;\r
88         endRes = end;\r
89         recalcConservation();\r
90     }\r
91 \r
92     /**\r
93      * Creates a new SequenceGroup object.\r
94      *\r
95      * @param groupName DOCUMENT ME!\r
96      * @param scheme DOCUMENT ME!\r
97      * @param displayBoxes DOCUMENT ME!\r
98      * @param displayText DOCUMENT ME!\r
99      * @param colourText DOCUMENT ME!\r
100      * @param start DOCUMENT ME!\r
101      * @param end DOCUMENT ME!\r
102      */\r
103     public SequenceGroup(String groupName, ColourSchemeI scheme,\r
104         boolean displayBoxes, boolean displayText, boolean colourText,\r
105         int start, int end)\r
106     {\r
107         this.groupName = groupName;\r
108         this.displayBoxes = displayBoxes;\r
109         this.displayText = displayText;\r
110         this.colourText = colourText;\r
111         this.cs = scheme;\r
112         startRes = start;\r
113         endRes = end;\r
114     }\r
115 \r
116     public SequenceI [] getSelectionAsNewSequences(AlignmentI align)\r
117     {\r
118       int iSize = sequences.size();\r
119       SequenceI [] seqs = new SequenceI[iSize];\r
120       SequenceI [] inorder = getSequencesInOrder(align);\r
121 \r
122     for (int i = 0; i < iSize; i++)\r
123     {\r
124       SequenceI seq = inorder[i];\r
125 \r
126       seqs[i] = new Sequence(seq.getName(),\r
127                              seq.getSequence(startRes, endRes + 1),\r
128                              seq.findPosition(startRes),\r
129                              findEndRes(seq));\r
130 \r
131       seqs[i].setDescription(seq.getDescription());\r
132       seqs[i].setDBRef(seq.getDBRef());\r
133       seqs[i].setSequenceFeatures(seq.getSequenceFeatures());\r
134       if (seq.getDatasetSequence() != null)\r
135         seqs[i].setDatasetSequence(seq.getDatasetSequence());\r
136 \r
137       if(seq.getAnnotation()!=null)\r
138       {\r
139         for(int a=0; a<seq.getAnnotation().length; a++)\r
140           seqs[i].addAlignmentAnnotation(seq.getAnnotation()[a]);\r
141       }\r
142     }\r
143 \r
144     return seqs;\r
145 \r
146     }\r
147 \r
148     /**\r
149      * If sequence ends in gaps, the end residue can\r
150      * be correctly calculated here\r
151      * @param seq SequenceI\r
152      * @return int\r
153      */\r
154     public int findEndRes(SequenceI seq)\r
155     {\r
156       int eres = 0;\r
157       char ch;\r
158 \r
159       for (int j = 0; j < endRes + 1 && j < seq.getLength(); j++)\r
160       {\r
161         ch = seq.getCharAt(j);\r
162         if (!jalview.util.Comparison.isGap( (ch)))\r
163         {\r
164           eres++;\r
165         }\r
166       }\r
167 \r
168       if (eres > 0)\r
169       {\r
170         eres += seq.getStart() - 1;\r
171       }\r
172 \r
173       return eres;\r
174     }\r
175 \r
176     public Vector getSequences(boolean includeHidden)\r
177     {\r
178       if(!includeHidden)\r
179         return sequences;\r
180       else\r
181       {\r
182         Vector allSequences = new Vector();\r
183         SequenceI seq;\r
184         for (int i = 0; i < sequences.size(); i++)\r
185         {\r
186           seq = (SequenceI) sequences.elementAt(i);\r
187           allSequences.addElement(seq);\r
188           if (seq.getHiddenSequences() != null)\r
189           {\r
190             for (int h = 0; h < seq.getHiddenSequences().getSize(false); h++)\r
191             {\r
192               allSequences.addElement(\r
193                   seq.getHiddenSequences().getSequenceAt(h)\r
194                   );\r
195             }\r
196           }\r
197         }\r
198 \r
199         return allSequences;\r
200       }\r
201     }\r
202 \r
203     public SequenceI[] getSequencesAsArray(boolean includeHidden)\r
204     {\r
205       Vector tmp = getSequences(includeHidden);\r
206       if(tmp==null)\r
207         return null;\r
208       SequenceI [] result = new SequenceI[tmp.size()];\r
209       for(int i=0; i<result.length; i++)\r
210         result[i] = (SequenceI)tmp.elementAt(i);\r
211 \r
212       return result;\r
213     }\r
214 \r
215     /**\r
216      * DOCUMENT ME!\r
217      *\r
218      * @param col DOCUMENT ME!\r
219      *\r
220      * @return DOCUMENT ME!\r
221      */\r
222     public boolean adjustForRemoveLeft(int col)\r
223     {\r
224         // return value is true if the group still exists\r
225         if (startRes >= col)\r
226         {\r
227             startRes = startRes - col;\r
228         }\r
229 \r
230         if (endRes >= col)\r
231         {\r
232             endRes = endRes - col;\r
233 \r
234             if (startRes > endRes)\r
235             {\r
236                 startRes = 0;\r
237             }\r
238         }\r
239         else\r
240         {\r
241             // must delete this group!!\r
242             return false;\r
243         }\r
244 \r
245         return true;\r
246     }\r
247 \r
248     /**\r
249      * DOCUMENT ME!\r
250      *\r
251      * @param col DOCUMENT ME!\r
252      *\r
253      * @return DOCUMENT ME!\r
254      */\r
255     public boolean adjustForRemoveRight(int col)\r
256     {\r
257         if (startRes > col)\r
258         {\r
259             // delete this group\r
260             return false;\r
261         }\r
262 \r
263         if (endRes >= col)\r
264         {\r
265             endRes = col;\r
266         }\r
267 \r
268         return true;\r
269     }\r
270 \r
271     /**\r
272      * DOCUMENT ME!\r
273      *\r
274      * @return DOCUMENT ME!\r
275      */\r
276     public String getName()\r
277     {\r
278         return groupName;\r
279     }\r
280 \r
281     /**\r
282      * DOCUMENT ME!\r
283      *\r
284      * @param name DOCUMENT ME!\r
285      */\r
286     public void setName(String name)\r
287     {\r
288         groupName = name;\r
289     }\r
290 \r
291     /**\r
292      * DOCUMENT ME!\r
293      *\r
294      * @return DOCUMENT ME!\r
295      */\r
296     public Conservation getConservation()\r
297     {\r
298         return conserve;\r
299     }\r
300 \r
301     /**\r
302      * DOCUMENT ME!\r
303      *\r
304      * @param c DOCUMENT ME!\r
305      */\r
306     public void setConservation(Conservation c)\r
307     {\r
308         conserve = c;\r
309     }\r
310 \r
311     /**\r
312      * DOCUMENT ME!\r
313      *\r
314      * @param s DOCUMENT ME!\r
315      * @param recalc DOCUMENT ME!\r
316      */\r
317     public void addSequence(SequenceI s, boolean recalc)\r
318     {\r
319         if (!sequences.contains(s))\r
320         {\r
321             sequences.addElement(s);\r
322         }\r
323 \r
324         if (recalc)\r
325         {\r
326             recalcConservation();\r
327         }\r
328     }\r
329 \r
330     /**\r
331      * DOCUMENT ME!\r
332      */\r
333     public void recalcConservation()\r
334     {\r
335         if(cs == null)\r
336           return;\r
337 \r
338         try\r
339         {\r
340           cs.setConsensus(AAFrequency.calculate(sequences, 0, getWidth()));\r
341 \r
342           if (cs instanceof ClustalxColourScheme)\r
343           {\r
344             ( (ClustalxColourScheme) cs).resetClustalX(sequences, getWidth());\r
345           }\r
346 \r
347           if (cs.conservationApplied())\r
348           {\r
349             Conservation c = new Conservation(groupName,\r
350                                               ResidueProperties.propHash, 3, sequences,\r
351                                               0, getWidth());\r
352             c.calculate();\r
353             c.verdict(false, 25);\r
354 \r
355             cs.setConservation(c);\r
356 \r
357             if (cs instanceof ClustalxColourScheme)\r
358             {\r
359               ( (ClustalxColourScheme) cs).resetClustalX(sequences,\r
360                                                          getWidth());\r
361             }\r
362           }\r
363         }\r
364         catch (java.lang.OutOfMemoryError err)\r
365         {\r
366           System.out.println("Out of memory loading groups: " + err);\r
367         }\r
368 \r
369     }\r
370 \r
371     /**\r
372      * DOCUMENT ME!\r
373      *\r
374      * @param s DOCUMENT ME!\r
375      * @param recalc DOCUMENT ME!\r
376      */\r
377     public void addOrRemove(SequenceI s, boolean recalc)\r
378     {\r
379         if (sequences.contains(s))\r
380         {\r
381             deleteSequence(s, recalc);\r
382         }\r
383         else\r
384         {\r
385             addSequence(s, recalc);\r
386         }\r
387     }\r
388 \r
389     /**\r
390      * DOCUMENT ME!\r
391      *\r
392      * @param s DOCUMENT ME!\r
393      * @param recalc DOCUMENT ME!\r
394      */\r
395     public void deleteSequence(SequenceI s, boolean recalc)\r
396     {\r
397         sequences.removeElement(s);\r
398 \r
399         if (recalc)\r
400         {\r
401             recalcConservation();\r
402         }\r
403     }\r
404 \r
405     /**\r
406      * DOCUMENT ME!\r
407      *\r
408      * @return DOCUMENT ME!\r
409      */\r
410     public int getStartRes()\r
411     {\r
412         return startRes;\r
413     }\r
414 \r
415     /**\r
416      * DOCUMENT ME!\r
417      *\r
418      * @return DOCUMENT ME!\r
419      */\r
420     public int getEndRes()\r
421     {\r
422         return endRes;\r
423     }\r
424 \r
425     /**\r
426      * DOCUMENT ME!\r
427      *\r
428      * @param i DOCUMENT ME!\r
429      */\r
430     public void setStartRes(int i)\r
431     {\r
432         startRes = i;\r
433     }\r
434 \r
435     /**\r
436      * DOCUMENT ME!\r
437      *\r
438      * @param i DOCUMENT ME!\r
439      */\r
440     public void setEndRes(int i)\r
441     {\r
442         endRes = i;\r
443     }\r
444 \r
445     /**\r
446      * DOCUMENT ME!\r
447      *\r
448      * @return DOCUMENT ME!\r
449      */\r
450     public int getSize(boolean includeHidden)\r
451     {\r
452       if(!includeHidden)\r
453         return sequences.size();\r
454       else\r
455       {\r
456         int total = sequences.size();\r
457         SequenceI seq;\r
458         for (int i = 0; i < sequences.size(); i++)\r
459         {\r
460           seq = (SequenceI) sequences.elementAt(i);\r
461           if (seq.getHiddenSequences() != null)\r
462           {\r
463             total += seq.getHiddenSequences().getSize(false);\r
464           }\r
465         }\r
466         return total;\r
467       }\r
468     }\r
469 \r
470     /**\r
471      * DOCUMENT ME!\r
472      *\r
473      * @param i DOCUMENT ME!\r
474      *\r
475      * @return DOCUMENT ME!\r
476      */\r
477     public SequenceI getSequenceAt(int i)\r
478     {\r
479         return (SequenceI) sequences.elementAt(i);\r
480     }\r
481 \r
482     /**\r
483      * DOCUMENT ME!\r
484      *\r
485      * @param state DOCUMENT ME!\r
486      */\r
487     public void setColourText(boolean state)\r
488     {\r
489         colourText = state;\r
490     }\r
491 \r
492     /**\r
493      * DOCUMENT ME!\r
494      *\r
495      * @return DOCUMENT ME!\r
496      */\r
497     public boolean getColourText()\r
498     {\r
499         return colourText;\r
500     }\r
501 \r
502     /**\r
503      * DOCUMENT ME!\r
504      *\r
505      * @param state DOCUMENT ME!\r
506      */\r
507     public void setDisplayText(boolean state)\r
508     {\r
509         displayText = state;\r
510     }\r
511 \r
512     /**\r
513      * DOCUMENT ME!\r
514      *\r
515      * @return DOCUMENT ME!\r
516      */\r
517     public boolean getDisplayText()\r
518     {\r
519         return displayText;\r
520     }\r
521 \r
522     /**\r
523      * DOCUMENT ME!\r
524      *\r
525      * @param state DOCUMENT ME!\r
526      */\r
527     public void setDisplayBoxes(boolean state)\r
528     {\r
529         displayBoxes = state;\r
530     }\r
531 \r
532     /**\r
533      * DOCUMENT ME!\r
534      *\r
535      * @return DOCUMENT ME!\r
536      */\r
537     public boolean getDisplayBoxes()\r
538     {\r
539         return displayBoxes;\r
540     }\r
541 \r
542     /**\r
543      * DOCUMENT ME!\r
544      *\r
545      * @return DOCUMENT ME!\r
546      */\r
547     public int getWidth()\r
548     {\r
549         // MC This needs to get reset when characters are inserted and deleted\r
550         if (sequences.size() > 0)\r
551         {\r
552             width = ((SequenceI) sequences.elementAt(0)).getLength();\r
553         }\r
554 \r
555         for (int i = 1; i < sequences.size(); i++)\r
556         {\r
557             SequenceI seq = (SequenceI) sequences.elementAt(i);\r
558 \r
559             if (seq.getLength() > width)\r
560             {\r
561                 width = seq.getLength();\r
562             }\r
563         }\r
564 \r
565         return width;\r
566     }\r
567 \r
568     /**\r
569      * DOCUMENT ME!\r
570      *\r
571      * @param c DOCUMENT ME!\r
572      */\r
573     public void setOutlineColour(Color c)\r
574     {\r
575         outlineColour = c;\r
576     }\r
577 \r
578     /**\r
579      * DOCUMENT ME!\r
580      *\r
581      * @return DOCUMENT ME!\r
582      */\r
583     public Color getOutlineColour()\r
584     {\r
585         return outlineColour;\r
586     }\r
587 \r
588     /**\r
589      *\r
590      * returns the sequences in the group ordered by the ordering given by al\r
591      *\r
592      * @param al Alignment\r
593      * @return SequenceI[]\r
594      */\r
595     public SequenceI[] getSequencesInOrder(AlignmentI al)\r
596     {\r
597         int sSize = sequences.size();\r
598         int alHeight = al.getHeight();\r
599 \r
600         SequenceI[] seqs = new SequenceI[sSize];\r
601 \r
602         int index = 0;\r
603         for (int i = 0; i < alHeight && index<sSize; i++)\r
604         {\r
605           if(sequences.contains( al.getSequenceAt(i) ) )\r
606             seqs[index++] = al.getSequenceAt(i);\r
607         }\r
608 \r
609         return seqs;\r
610     }\r
611 }\r