dc22704ffebd62006b2d55be030b5ac20ee2e6d3
[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 \r
123     for (int i = 0; i < iSize; i++)\r
124     {\r
125       SequenceI seq = inorder[i];\r
126 \r
127       seqs[i] = new Sequence(seq.getName(),\r
128                              seq.getSequence(startRes, endRes + 1),\r
129                              seq.findPosition(startRes),\r
130                              findEndRes(seq));\r
131 \r
132       seqs[i].setDescription(seq.getDescription());\r
133       seqs[i].setDBRef(seq.getDBRef());\r
134       seqs[i].setSequenceFeatures(seq.getSequenceFeatures());\r
135       if (seq.getDatasetSequence() != null)\r
136         seqs[i].setDatasetSequence(seq.getDatasetSequence());\r
137 \r
138       if(seq.getAnnotation()!=null)\r
139       {\r
140         for(int a=0; a<seq.getAnnotation().length; a++)\r
141           seqs[i].addAlignmentAnnotation(seq.getAnnotation()[a]);\r
142       }\r
143     }\r
144 \r
145     return seqs;\r
146 \r
147     }\r
148 \r
149     /**\r
150      * If sequence ends in gaps, the end residue can\r
151      * be correctly calculated here\r
152      * @param seq SequenceI\r
153      * @return int\r
154      */\r
155     public int findEndRes(SequenceI seq)\r
156     {\r
157       int eres = 0;\r
158       char ch;\r
159 \r
160       for (int j = 0; j < endRes + 1 && j < seq.getLength(); j++)\r
161       {\r
162         ch = seq.getCharAt(j);\r
163         if (!jalview.util.Comparison.isGap( (ch)))\r
164         {\r
165           eres++;\r
166         }\r
167       }\r
168 \r
169       if (eres > 0)\r
170       {\r
171         eres += seq.getStart() - 1;\r
172       }\r
173 \r
174       return eres;\r
175     }\r
176 \r
177     public Vector getSequences(boolean includeHidden)\r
178     {\r
179       if(!includeHidden)\r
180         return sequences;\r
181       else\r
182       {\r
183         Vector allSequences = new Vector();\r
184         SequenceI seq;\r
185         for (int i = 0; i < sequences.size(); i++)\r
186         {\r
187           seq = (SequenceI) sequences.elementAt(i);\r
188           allSequences.addElement(seq);\r
189           if (seq.getHiddenSequences() != null)\r
190           {\r
191             for (int h = 0; h < seq.getHiddenSequences().getSize(false); h++)\r
192             {\r
193               allSequences.addElement(\r
194                   seq.getHiddenSequences().getSequenceAt(h)\r
195                   );\r
196             }\r
197           }\r
198         }\r
199 \r
200         return allSequences;\r
201       }\r
202     }\r
203 \r
204     public SequenceI[] getSequencesAsArray(boolean includeHidden)\r
205     {\r
206       Vector tmp = getSequences(includeHidden);\r
207       if(tmp==null)\r
208         return null;\r
209       SequenceI [] result = new SequenceI[tmp.size()];\r
210       for(int i=0; i<result.length; i++)\r
211         result[i] = (SequenceI)tmp.elementAt(i);\r
212 \r
213       return result;\r
214     }\r
215 \r
216     /**\r
217      * DOCUMENT ME!\r
218      *\r
219      * @param col DOCUMENT ME!\r
220      *\r
221      * @return DOCUMENT ME!\r
222      */\r
223     public boolean adjustForRemoveLeft(int col)\r
224     {\r
225         // return value is true if the group still exists\r
226         if (startRes >= col)\r
227         {\r
228             startRes = startRes - col;\r
229         }\r
230 \r
231         if (endRes >= col)\r
232         {\r
233             endRes = endRes - col;\r
234 \r
235             if (startRes > endRes)\r
236             {\r
237                 startRes = 0;\r
238             }\r
239         }\r
240         else\r
241         {\r
242             // must delete this group!!\r
243             return false;\r
244         }\r
245 \r
246         return true;\r
247     }\r
248 \r
249     /**\r
250      * DOCUMENT ME!\r
251      *\r
252      * @param col DOCUMENT ME!\r
253      *\r
254      * @return DOCUMENT ME!\r
255      */\r
256     public boolean adjustForRemoveRight(int col)\r
257     {\r
258         if (startRes > col)\r
259         {\r
260             // delete this group\r
261             return false;\r
262         }\r
263 \r
264         if (endRes >= col)\r
265         {\r
266             endRes = col;\r
267         }\r
268 \r
269         return true;\r
270     }\r
271 \r
272     /**\r
273      * DOCUMENT ME!\r
274      *\r
275      * @return DOCUMENT ME!\r
276      */\r
277     public String getName()\r
278     {\r
279         return groupName;\r
280     }\r
281 \r
282     /**\r
283      * DOCUMENT ME!\r
284      *\r
285      * @param name DOCUMENT ME!\r
286      */\r
287     public void setName(String name)\r
288     {\r
289         groupName = name;\r
290     }\r
291 \r
292     /**\r
293      * DOCUMENT ME!\r
294      *\r
295      * @return DOCUMENT ME!\r
296      */\r
297     public Conservation getConservation()\r
298     {\r
299         return conserve;\r
300     }\r
301 \r
302     /**\r
303      * DOCUMENT ME!\r
304      *\r
305      * @param c DOCUMENT ME!\r
306      */\r
307     public void setConservation(Conservation c)\r
308     {\r
309         conserve = c;\r
310     }\r
311 \r
312     /**\r
313      * DOCUMENT ME!\r
314      *\r
315      * @param s DOCUMENT ME!\r
316      * @param recalc DOCUMENT ME!\r
317      */\r
318     public void addSequence(SequenceI s, boolean recalc)\r
319     {\r
320         if (s!=null && !sequences.contains(s))\r
321         {\r
322             sequences.addElement(s);\r
323         }\r
324 \r
325         if (recalc)\r
326         {\r
327             recalcConservation();\r
328         }\r
329     }\r
330 \r
331     /**\r
332      * DOCUMENT ME!\r
333      */\r
334     public void recalcConservation()\r
335     {\r
336         if(cs == null)\r
337           return;\r
338 \r
339         try\r
340         {\r
341           cs.setConsensus(AAFrequency.calculate(sequences, 0, getWidth()));\r
342 \r
343           if (cs instanceof ClustalxColourScheme)\r
344           {\r
345             ( (ClustalxColourScheme) cs).resetClustalX(sequences, getWidth());\r
346           }\r
347 \r
348           if (cs.conservationApplied())\r
349           {\r
350             Conservation c = new Conservation(groupName,\r
351                                               ResidueProperties.propHash, 3, sequences,\r
352                                               0, getWidth());\r
353             c.calculate();\r
354             c.verdict(false, 25);\r
355 \r
356             cs.setConservation(c);\r
357 \r
358             if (cs instanceof ClustalxColourScheme)\r
359             {\r
360               ( (ClustalxColourScheme) cs).resetClustalX(sequences,\r
361                                                          getWidth());\r
362             }\r
363           }\r
364         }\r
365         catch (java.lang.OutOfMemoryError err)\r
366         {\r
367           System.out.println("Out of memory loading groups: " + err);\r
368         }\r
369 \r
370     }\r
371 \r
372     /**\r
373      * DOCUMENT ME!\r
374      *\r
375      * @param s DOCUMENT ME!\r
376      * @param recalc DOCUMENT ME!\r
377      */\r
378     public void addOrRemove(SequenceI s, boolean recalc)\r
379     {\r
380         if (sequences.contains(s))\r
381         {\r
382             deleteSequence(s, recalc);\r
383         }\r
384         else\r
385         {\r
386             addSequence(s, recalc);\r
387         }\r
388     }\r
389 \r
390     /**\r
391      * DOCUMENT ME!\r
392      *\r
393      * @param s DOCUMENT ME!\r
394      * @param recalc DOCUMENT ME!\r
395      */\r
396     public void deleteSequence(SequenceI s, boolean recalc)\r
397     {\r
398         sequences.removeElement(s);\r
399 \r
400         if (recalc)\r
401         {\r
402             recalcConservation();\r
403         }\r
404     }\r
405 \r
406     /**\r
407      * DOCUMENT ME!\r
408      *\r
409      * @return DOCUMENT ME!\r
410      */\r
411     public int getStartRes()\r
412     {\r
413         return startRes;\r
414     }\r
415 \r
416     /**\r
417      * DOCUMENT ME!\r
418      *\r
419      * @return DOCUMENT ME!\r
420      */\r
421     public int getEndRes()\r
422     {\r
423         return endRes;\r
424     }\r
425 \r
426     /**\r
427      * DOCUMENT ME!\r
428      *\r
429      * @param i DOCUMENT ME!\r
430      */\r
431     public void setStartRes(int i)\r
432     {\r
433         startRes = i;\r
434     }\r
435 \r
436     /**\r
437      * DOCUMENT ME!\r
438      *\r
439      * @param i DOCUMENT ME!\r
440      */\r
441     public void setEndRes(int i)\r
442     {\r
443         endRes = i;\r
444     }\r
445 \r
446     /**\r
447      * DOCUMENT ME!\r
448      *\r
449      * @return DOCUMENT ME!\r
450      */\r
451     public int getSize(boolean includeHidden)\r
452     {\r
453       if(!includeHidden)\r
454         return sequences.size();\r
455       else\r
456       {\r
457         int total = sequences.size();\r
458         SequenceI seq;\r
459         for (int i = 0; i < sequences.size(); i++)\r
460         {\r
461           seq = (SequenceI) sequences.elementAt(i);\r
462           if (seq.getHiddenSequences() != null)\r
463           {\r
464             total += seq.getHiddenSequences().getSize(false);\r
465           }\r
466         }\r
467         return total;\r
468       }\r
469     }\r
470 \r
471     /**\r
472      * DOCUMENT ME!\r
473      *\r
474      * @param i DOCUMENT ME!\r
475      *\r
476      * @return DOCUMENT ME!\r
477      */\r
478     public SequenceI getSequenceAt(int i)\r
479     {\r
480         return (SequenceI) sequences.elementAt(i);\r
481     }\r
482 \r
483     /**\r
484      * DOCUMENT ME!\r
485      *\r
486      * @param state DOCUMENT ME!\r
487      */\r
488     public void setColourText(boolean state)\r
489     {\r
490         colourText = state;\r
491     }\r
492 \r
493     /**\r
494      * DOCUMENT ME!\r
495      *\r
496      * @return DOCUMENT ME!\r
497      */\r
498     public boolean getColourText()\r
499     {\r
500         return colourText;\r
501     }\r
502 \r
503     /**\r
504      * DOCUMENT ME!\r
505      *\r
506      * @param state DOCUMENT ME!\r
507      */\r
508     public void setDisplayText(boolean state)\r
509     {\r
510         displayText = state;\r
511     }\r
512 \r
513     /**\r
514      * DOCUMENT ME!\r
515      *\r
516      * @return DOCUMENT ME!\r
517      */\r
518     public boolean getDisplayText()\r
519     {\r
520         return displayText;\r
521     }\r
522 \r
523     /**\r
524      * DOCUMENT ME!\r
525      *\r
526      * @param state DOCUMENT ME!\r
527      */\r
528     public void setDisplayBoxes(boolean state)\r
529     {\r
530         displayBoxes = state;\r
531     }\r
532 \r
533     /**\r
534      * DOCUMENT ME!\r
535      *\r
536      * @return DOCUMENT ME!\r
537      */\r
538     public boolean getDisplayBoxes()\r
539     {\r
540         return displayBoxes;\r
541     }\r
542 \r
543     /**\r
544      * DOCUMENT ME!\r
545      *\r
546      * @return DOCUMENT ME!\r
547      */\r
548     public int getWidth()\r
549     {\r
550         // MC This needs to get reset when characters are inserted and deleted\r
551         if (sequences.size() > 0)\r
552         {\r
553             width = ((SequenceI) sequences.elementAt(0)).getLength();\r
554         }\r
555 \r
556         for (int i = 1; i < sequences.size(); i++)\r
557         {\r
558             SequenceI seq = (SequenceI) sequences.elementAt(i);\r
559 \r
560             if (seq.getLength() > width)\r
561             {\r
562                 width = seq.getLength();\r
563             }\r
564         }\r
565 \r
566         return width;\r
567     }\r
568 \r
569     /**\r
570      * DOCUMENT ME!\r
571      *\r
572      * @param c DOCUMENT ME!\r
573      */\r
574     public void setOutlineColour(Color c)\r
575     {\r
576         outlineColour = c;\r
577     }\r
578 \r
579     /**\r
580      * DOCUMENT ME!\r
581      *\r
582      * @return DOCUMENT ME!\r
583      */\r
584     public Color getOutlineColour()\r
585     {\r
586         return outlineColour;\r
587     }\r
588 \r
589     /**\r
590      *\r
591      * returns the sequences in the group ordered by the ordering given by al\r
592      *\r
593      * @param al Alignment\r
594      * @return SequenceI[]\r
595      */\r
596     public SequenceI[] getSequencesInOrder(AlignmentI al)\r
597     {\r
598         int sSize = sequences.size();\r
599         int alHeight = al.getHeight();\r
600 \r
601         SequenceI[] seqs = new SequenceI[sSize];\r
602 \r
603         int index = 0;\r
604         for (int i = 0; i < alHeight && index<sSize; i++)\r
605         {\r
606           if(sequences.contains( al.getSequenceAt(i) ) )\r
607             seqs[index++] = al.getSequenceAt(i);\r
608         }\r
609 \r
610         return seqs;\r
611     }\r
612 }\r