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