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