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