Formatted source
[jalview.git] / src / jalview / appletgui / AlignViewport.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 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 \r
20 package jalview.appletgui;\r
21 \r
22 import java.util.*;\r
23 \r
24 import java.awt.*;\r
25 \r
26 import jalview.analysis.*;\r
27 import jalview.bin.*;\r
28 import jalview.datamodel.*;\r
29 import jalview.schemes.*;\r
30 \r
31 public class AlignViewport\r
32 {\r
33   int startRes;\r
34   int endRes;\r
35 \r
36   int startSeq;\r
37   int endSeq;\r
38 \r
39   boolean showFullId = true;\r
40   boolean showText = true;\r
41   boolean showColourText = false;\r
42   boolean showBoxes = true;\r
43   boolean wrapAlignment = false;\r
44   boolean renderGaps = true;\r
45   boolean showSequenceFeatures = false;\r
46   boolean showAnnotation = true;\r
47   boolean showConservation = true;\r
48   boolean showQuality = true;\r
49   boolean showConsensus = true;\r
50 \r
51   boolean colourAppliesToAllGroups = true;\r
52   ColourSchemeI globalColourScheme = null;\r
53   boolean conservationColourSelected = false;\r
54   boolean abovePIDThreshold = false;\r
55 \r
56   SequenceGroup selectionGroup = new SequenceGroup();\r
57 \r
58   int charHeight;\r
59   int charWidth;\r
60   int chunkWidth;\r
61   int chunkHeight;\r
62 \r
63   Font font = new Font("SansSerif", Font.PLAIN, 10);\r
64   AlignmentI alignment;\r
65 \r
66   ColumnSelection colSel = new ColumnSelection();\r
67 \r
68   int threshold;\r
69   int increment;\r
70 \r
71   NJTree currentTree = null;\r
72 \r
73   boolean scaleAboveWrapped = true;\r
74   boolean scaleLeftWrapped = true;\r
75   boolean scaleRightWrapped = true;\r
76 \r
77   public AlignViewport(AlignmentI al, JalviewLite applet)\r
78   {\r
79     setAlignment(al);\r
80     this.startRes = 0;\r
81     this.endRes = al.getWidth() - 1;\r
82     this.startSeq = 0;\r
83     this.endSeq = al.getHeight() - 1;\r
84     setFont(font);\r
85 \r
86     if (applet != null)\r
87     {\r
88       String param = applet.getParameter("showFullId");\r
89       if (param != null)\r
90       {\r
91         showFullId = Boolean.valueOf(param).booleanValue();\r
92       }\r
93 \r
94       param = applet.getParameter("showAnnotation");\r
95       if (param != null)\r
96       {\r
97         showAnnotation = Boolean.valueOf(param).booleanValue();\r
98       }\r
99 \r
100       param = applet.getParameter("showConservation");\r
101       if (param != null)\r
102       {\r
103         showConservation = Boolean.valueOf(param).booleanValue();\r
104       }\r
105 \r
106       param = applet.getParameter("showQuality");\r
107       if (param != null)\r
108       {\r
109         showQuality = Boolean.valueOf(param).booleanValue();\r
110       }\r
111 \r
112       param = applet.getParameter("showConsensus");\r
113       if (param != null)\r
114       {\r
115         showConsensus = Boolean.valueOf(param).booleanValue();\r
116       }\r
117     }\r
118     // We must set conservation and consensus before setting colour,\r
119     // as Blosum and Clustal require this to be done\r
120     updateConservation();\r
121     updateConsensus();\r
122 \r
123     if (applet != null && applet.getParameter("defaultColour") != null)\r
124     {\r
125       globalColourScheme = ColourSchemeProperty.getColour(alignment,\r
126           applet.getParameter("defaultColour"));\r
127       if (globalColourScheme != null)\r
128       {\r
129         globalColourScheme.setConsensus(vconsensus);\r
130       }\r
131     }\r
132   }\r
133 \r
134   public void showSequenceFeatures(boolean b)\r
135   {\r
136     showSequenceFeatures = b;\r
137   }\r
138 \r
139   public Vector vconsensus;\r
140   AlignmentAnnotation consensus;\r
141   AlignmentAnnotation conservation;\r
142   AlignmentAnnotation quality;\r
143 \r
144   public int ConsPercGaps = 25; // JBPNote : This should be a scalable property!\r
145 \r
146   public void updateConservation()\r
147   {\r
148     Conservation cons = new jalview.analysis.Conservation("All",\r
149         jalview.schemes.ResidueProperties.propHash, 3,\r
150         alignment.getSequences(), 0,\r
151         alignment.getWidth() - 1);\r
152     cons.calculate();\r
153     cons.verdict(false, ConsPercGaps);\r
154     cons.findQuality();\r
155     int alWidth = alignment.getWidth();\r
156     Annotation[] annotations = new Annotation[alWidth];\r
157     Annotation[] qannotations = new Annotation[alWidth];\r
158     String sequence = cons.getConsSequence().getSequence();\r
159     float minR, minG, minB, maxR, maxG, maxB;\r
160     minR = 0.3f;\r
161     minG = 0.0f;\r
162     minB = 0f;\r
163     maxR = 1.0f - minR;\r
164     maxG = 0.9f - minG;\r
165     maxB = 0f - minB; // scalable range for colouring both Conservation and Quality\r
166     float min = 0f;\r
167     float max = 11f;\r
168     float qmin = cons.qualityRange[0].floatValue();\r
169     float qmax = cons.qualityRange[1].floatValue();\r
170 \r
171     for (int i = 0; i < alWidth; i++)\r
172     {\r
173       float value = 0;\r
174       try\r
175       {\r
176         value = Integer.parseInt(sequence.charAt(i) + "");\r
177       }\r
178       catch (Exception ex)\r
179       {\r
180         if (sequence.charAt(i) == '*')\r
181         {\r
182           value = 11;\r
183         }\r
184         if (sequence.charAt(i) == '+')\r
185         {\r
186           value = 10;\r
187         }\r
188       }\r
189       float vprop = value - min;\r
190       vprop /= max;\r
191 \r
192       annotations[i] = new Annotation(sequence.charAt(i) + "",\r
193                                       "", ' ', value,\r
194                                       new Color(minR + maxR * vprop,\r
195                                                 minG + maxG * vprop,\r
196                                                 minB + maxB * vprop));\r
197       // Quality calc\r
198       value = ( (Double) cons.quality.elementAt(i)).floatValue();\r
199       vprop = value - qmin;\r
200       vprop /= qmax;\r
201       qannotations[i] = new Annotation(" ",\r
202                                        String.valueOf(value), ' ', value,\r
203                                        new\r
204                                        Color(minR + maxR * vprop,\r
205                                              minG + maxG * vprop,\r
206                                              minB + maxB * vprop));\r
207     }\r
208 \r
209     if (conservation == null)\r
210     {\r
211       conservation = new AlignmentAnnotation("Conservation",\r
212                                              "Conservation of total alignment less than " +\r
213                                              ConsPercGaps + "% gaps",\r
214                                              annotations,\r
215                                              0f, // cons.qualityRange[0].floatValue(),\r
216                                              11f, // cons.qualityRange[1].floatValue()\r
217                                              1);\r
218       if (showConservation)\r
219       {\r
220         alignment.addAnnotation(conservation);\r
221       }\r
222       quality = new AlignmentAnnotation("Quality",\r
223                                         "Alignment Quality based on Blosum62 scores",\r
224                                         qannotations,\r
225                                         cons.qualityRange[0].floatValue(),\r
226                                         cons.qualityRange[1].floatValue(),\r
227                                         1);\r
228       if (showQuality)\r
229       {\r
230         alignment.addAnnotation(quality);\r
231       }\r
232     }\r
233     else\r
234     {\r
235       conservation.annotations = annotations;\r
236       quality.annotations = qannotations;\r
237       quality.graphMax = cons.qualityRange[1].floatValue();\r
238     }\r
239 \r
240   }\r
241 \r
242   public void updateConsensus()\r
243   {\r
244     Annotation[] annotations = new Annotation[alignment.getWidth()];\r
245 \r
246     // this routine prevents vconsensus becoming a new object each time\r
247     // consenus is calculated. Important for speed of Blosum62\r
248     // and PID colouring of alignment\r
249     if (vconsensus == null)\r
250     {\r
251       vconsensus = alignment.getAAFrequency();\r
252     }\r
253     else\r
254     {\r
255       Vector temp = alignment.getAAFrequency();\r
256       vconsensus.removeAllElements();\r
257       Enumeration e = temp.elements();\r
258       while (e.hasMoreElements())\r
259       {\r
260         vconsensus.addElement(e.nextElement());\r
261       }\r
262     }\r
263     Hashtable hash = null;\r
264     for (int i = 0; i < alignment.getWidth(); i++)\r
265     {\r
266       hash = (Hashtable) vconsensus.elementAt(i);\r
267       float value = new Float(hash.get("maxCount").toString()).floatValue();\r
268       value /= new Float(hash.get("size").toString()).floatValue();\r
269 \r
270       value *= 100;\r
271       String maxRes = hash.get("maxResidue") + " ";\r
272       String mouseOver = hash.get("maxResidue") + " ";\r
273       if (maxRes.length() > 2)\r
274       {\r
275         mouseOver = "[" + maxRes + "] ";\r
276         maxRes = "+ ";\r
277       }\r
278 \r
279       mouseOver += (int) value + "%";\r
280       annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);\r
281 \r
282     }\r
283 \r
284     if (consensus == null)\r
285     {\r
286       consensus = new AlignmentAnnotation("Consensus",\r
287                                           "PID", annotations, 0f, 100f, 1);\r
288       if (showConsensus)\r
289       {\r
290         alignment.addAnnotation(consensus);\r
291       }\r
292     }\r
293     else\r
294     {\r
295       consensus.annotations = annotations;\r
296     }\r
297 \r
298   }\r
299 \r
300   public SequenceGroup getSelectionGroup()\r
301   {\r
302     return selectionGroup;\r
303   }\r
304 \r
305   public void setSelectionGroup(SequenceGroup sg)\r
306   {\r
307     selectionGroup = sg;\r
308   }\r
309 \r
310   public boolean getConservationSelected()\r
311   {\r
312     return conservationColourSelected;\r
313   }\r
314 \r
315   public void setConservationSelected(boolean b)\r
316   {\r
317     conservationColourSelected = b;\r
318   }\r
319 \r
320   public boolean getAbovePIDThreshold()\r
321   {\r
322     return abovePIDThreshold;\r
323   }\r
324 \r
325   public void setAbovePIDThreshold(boolean b)\r
326   {\r
327     abovePIDThreshold = b;\r
328   }\r
329 \r
330   public int getStartRes()\r
331   {\r
332     return startRes;\r
333   }\r
334 \r
335   public int getEndRes()\r
336   {\r
337     return endRes;\r
338   }\r
339 \r
340   public int getStartSeq()\r
341   {\r
342     return startSeq;\r
343   }\r
344 \r
345   public void setGlobalColourScheme(ColourSchemeI cs)\r
346   {\r
347     globalColourScheme = cs;\r
348   }\r
349 \r
350   public ColourSchemeI getGlobalColourScheme()\r
351   {\r
352     return globalColourScheme;\r
353   }\r
354 \r
355   public void setStartRes(int res)\r
356   {\r
357     this.startRes = res;\r
358   }\r
359 \r
360   public void setStartSeq(int seq)\r
361   {\r
362     this.startSeq = seq;\r
363   }\r
364 \r
365   public void setEndRes(int res)\r
366   {\r
367     if (res > alignment.getWidth() - 1)\r
368     {\r
369       // log.System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));\r
370       res = alignment.getWidth() - 1;\r
371     }\r
372     if (res < 0)\r
373     {\r
374       res = 0;\r
375     }\r
376     this.endRes = res;\r
377   }\r
378 \r
379   public void setEndSeq(int seq)\r
380   {\r
381     if (seq > alignment.getHeight())\r
382     {\r
383       seq = alignment.getHeight();\r
384     }\r
385     if (seq < 0)\r
386     {\r
387       seq = 0;\r
388     }\r
389     this.endSeq = seq;\r
390   }\r
391 \r
392   public int getEndSeq()\r
393   {\r
394     return endSeq;\r
395   }\r
396 \r
397   public void setFont(Font f)\r
398   {\r
399     font = f;\r
400     java.awt.Frame temp = new java.awt.Frame();\r
401     temp.addNotify();\r
402     java.awt.FontMetrics fm = temp.getGraphics().getFontMetrics(font);\r
403     setCharHeight(fm.getHeight());\r
404     setCharWidth(fm.charWidth('M'));\r
405   }\r
406 \r
407   public Font getFont()\r
408   {\r
409     return font;\r
410   }\r
411 \r
412   public void setCharWidth(int w)\r
413   {\r
414     this.charWidth = w;\r
415   }\r
416 \r
417   public int getCharWidth()\r
418   {\r
419     return charWidth;\r
420   }\r
421 \r
422   public void setCharHeight(int h)\r
423   {\r
424     this.charHeight = h;\r
425   }\r
426 \r
427   public int getCharHeight()\r
428   {\r
429     return charHeight;\r
430   }\r
431 \r
432   public void setChunkWidth(int w)\r
433   {\r
434     this.chunkWidth = w;\r
435   }\r
436 \r
437   public int getChunkWidth()\r
438   {\r
439     return chunkWidth;\r
440   }\r
441 \r
442   public void setChunkHeight(int h)\r
443   {\r
444     this.chunkHeight = h;\r
445   }\r
446 \r
447   public int getChunkHeight()\r
448   {\r
449     return chunkHeight;\r
450   }\r
451 \r
452   public AlignmentI getAlignment()\r
453   {\r
454     return alignment;\r
455   }\r
456 \r
457   public void setAlignment(AlignmentI align)\r
458   {\r
459     this.alignment = align;\r
460   }\r
461 \r
462   public void setWrapAlignment(boolean state)\r
463   {\r
464     wrapAlignment = state;\r
465   }\r
466 \r
467   public void setShowText(boolean state)\r
468   {\r
469     showText = state;\r
470   }\r
471 \r
472   public void setRenderGaps(boolean state)\r
473   {\r
474     renderGaps = state;\r
475   }\r
476 \r
477   public boolean getColourText()\r
478   {\r
479     return showColourText;\r
480   }\r
481 \r
482   public void setColourText(boolean state)\r
483   {\r
484     showColourText = state;\r
485   }\r
486 \r
487   public void setShowBoxes(boolean state)\r
488   {\r
489     showBoxes = state;\r
490   }\r
491 \r
492   public boolean getWrapAlignment()\r
493   {\r
494     return wrapAlignment;\r
495   }\r
496 \r
497   public boolean getShowText()\r
498   {\r
499     return showText;\r
500   }\r
501 \r
502   public boolean getShowBoxes()\r
503   {\r
504     return showBoxes;\r
505   }\r
506 \r
507   public char getGapCharacter()\r
508   {\r
509     return getAlignment().getGapCharacter();\r
510   }\r
511 \r
512   public void setGapCharacter(char gap)\r
513   {\r
514     if (getAlignment() != null)\r
515     {\r
516       getAlignment().setGapCharacter(gap);\r
517     }\r
518   }\r
519 \r
520   public void setThreshold(int thresh)\r
521   {\r
522     threshold = thresh;\r
523   }\r
524 \r
525   public int getThreshold()\r
526   {\r
527     return threshold;\r
528   }\r
529 \r
530   public void setIncrement(int inc)\r
531   {\r
532     increment = inc;\r
533   }\r
534 \r
535   public int getIncrement()\r
536   {\r
537     return increment;\r
538   }\r
539 \r
540   public int getIndex(int y)\r
541   {\r
542     int y1 = 0;\r
543     int starty = getStartSeq();\r
544     int endy = getEndSeq();\r
545 \r
546     for (int i = starty; i <= endy; i++)\r
547     {\r
548       if (i < alignment.getHeight() && alignment.getSequenceAt(i) != null)\r
549       {\r
550         int y2 = y1 + getCharHeight();\r
551 \r
552         if (y >= y1 && y <= y2)\r
553         {\r
554           return i;\r
555         }\r
556         y1 = y2;\r
557       }\r
558       else\r
559       {\r
560         return -1;\r
561       }\r
562     }\r
563     return -1;\r
564   }\r
565 \r
566   public ColumnSelection getColumnSelection()\r
567   {\r
568     return colSel;\r
569   }\r
570 \r
571   public void resetSeqLimits(int height)\r
572   {\r
573     setEndSeq(height / getCharHeight());\r
574   }\r
575 \r
576   public void setCurrentTree(NJTree tree)\r
577   {\r
578     currentTree = tree;\r
579   }\r
580 \r
581   public NJTree getCurrentTree()\r
582   {\r
583     return currentTree;\r
584   }\r
585 \r
586   public void setColourAppliesToAllGroups(boolean b)\r
587   {\r
588     colourAppliesToAllGroups = b;\r
589   }\r
590 \r
591   public boolean getColourAppliesToAllGroups()\r
592   {\r
593     return colourAppliesToAllGroups;\r
594   }\r
595 \r
596   public boolean getShowFullId()\r
597   {\r
598     return showFullId;\r
599   }\r
600 \r
601   public void setShowFullId(boolean b)\r
602   {\r
603     showFullId = b;\r
604   }\r
605 \r
606   public boolean getShowAnnotation()\r
607   {\r
608     return showAnnotation;\r
609   }\r
610 \r
611   public void setShowAnnotation(boolean b)\r
612   {\r
613     showAnnotation = b;\r
614   }\r
615 \r
616   public boolean getScaleAboveWrapped()\r
617   {\r
618     return scaleAboveWrapped;\r
619   }\r
620 \r
621   public boolean getScaleLeftWrapped()\r
622   {\r
623     return scaleLeftWrapped;\r
624   }\r
625 \r
626   public boolean getScaleRightWrapped()\r
627   {\r
628     return scaleRightWrapped;\r
629   }\r
630 \r
631   public void setScaleAboveWrapped(boolean b)\r
632   {\r
633     scaleAboveWrapped = b;\r
634   }\r
635 \r
636   public void setScaleLeftWrapped(boolean b)\r
637   {\r
638     scaleLeftWrapped = b;\r
639   }\r
640 \r
641   public void setScaleRightWrapped(boolean b)\r
642   {\r
643     scaleRightWrapped = b;\r
644   }\r
645 \r
646 }\r