a5fd31f9d7cfadcc080923b71bb70ba3cd037782
[jalview.git] / src / jalview / gui / AlignViewport.java
1 package jalview.gui;\r
2 \r
3 import java.awt.*;\r
4 import jalview.analysis.*;\r
5 import jalview.analysis.NJTree;\r
6 import jalview.datamodel.*;\r
7 import jalview.schemes.*;\r
8 import java.util.*;\r
9 import jalview.bin.Cache;\r
10 \r
11 public class AlignViewport\r
12 {\r
13   int startRes;\r
14   int endRes;\r
15 \r
16   int startSeq;\r
17   int endSeq;\r
18 \r
19   boolean showFullId = false;\r
20   boolean showText=true;\r
21   boolean showColourText=false;\r
22   boolean showBoxes=true;\r
23   boolean wrapAlignment=false;\r
24   boolean renderGaps = true;\r
25   boolean showSequenceFeatures = false;\r
26   boolean showAnnotation = true;\r
27   boolean showConservation = true;\r
28   boolean showQuality = true;\r
29   boolean showIdentity = true;\r
30 \r
31   boolean colourAppliesToAllGroups = true;\r
32   ColourSchemeI globalColourScheme = null;\r
33   boolean conservationColourSelected = false;\r
34   boolean abovePIDThreshold = false;\r
35 \r
36   SequenceGroup selectionGroup = new SequenceGroup();\r
37 \r
38 \r
39   int             charHeight;\r
40   int             charWidth;\r
41   int             chunkWidth;\r
42   int             chunkHeight;\r
43 \r
44   Font            font = new Font("SansSerif",Font.PLAIN,10);\r
45   AlignmentI      alignment;\r
46 \r
47   ColumnSelection colSel = new ColumnSelection();\r
48 \r
49   int threshold;\r
50   int increment;\r
51 \r
52   NJTree currentTree = null;\r
53 \r
54   boolean scaleAboveWrapped = false;\r
55   boolean scaleLeftWrapped  = true;\r
56   boolean scaleRightWrapped = true;\r
57 \r
58 \r
59   public AlignViewport(AlignmentI al)\r
60   {\r
61     setAlignment(al);\r
62     this.startRes = 0;\r
63     this.endRes = al.getWidth()-1;\r
64     this.startSeq = 0;\r
65     this.endSeq = al.getHeight()-1;\r
66 \r
67     updateFromPreferences();\r
68 \r
69   }\r
70 \r
71   public void updateFromPreferences()\r
72   {\r
73     showFullId = Preferences.showFullId;\r
74     showAnnotation = Preferences.showAnnotation;\r
75     showConservation = Preferences.showConservation;\r
76     showQuality = Preferences.showQuality;\r
77     showIdentity = Preferences.showIdentity;\r
78     showFullId = Preferences.showFullId;\r
79     String fontName = Preferences.fontName;\r
80     String fontStyle = Preferences.fontStyle;\r
81     String fontSize = Cache.getProperty("FONT_SIZE");\r
82     if (fontName != null && fontStyle != null && fontSize != null)\r
83     {\r
84       int style = 0;\r
85       if(fontStyle.equals("bold"))\r
86         style = 1;\r
87       else if(fontStyle.equals("italic"))\r
88         style = 2;\r
89       setFont(new Font(fontName, style, Integer.parseInt(fontSize)));\r
90     }\r
91     else\r
92       setFont(font);\r
93 \r
94     alignment.setGapCharacter(Preferences.gapSymbol);\r
95 \r
96     // We must set conservation and consensus before setting colour,\r
97     // as Blosum and Clustal require this to be done\r
98     updateConservation();\r
99     updateConsensus();\r
100     if(Preferences.defaultColour!=null)\r
101     {\r
102       globalColourScheme = ColourSchemeProperty.getColour(alignment, Preferences.defaultColour);\r
103       if(globalColourScheme instanceof UserColourScheme)\r
104        globalColourScheme = UserDefinedColours.loadDefaultColours();\r
105       if(globalColourScheme!=null)\r
106         globalColourScheme.setConsensus( vconsensus );\r
107    }\r
108 \r
109  }\r
110 \r
111  public void showSequenceFeatures(boolean b)\r
112  {\r
113    showSequenceFeatures = b;\r
114  }\r
115 \r
116   public Vector vconsensus;\r
117   AlignmentAnnotation consensus;\r
118   AlignmentAnnotation conservation;\r
119   AlignmentAnnotation quality;\r
120 \r
121   public int ConsPercGaps = 25; // JBPNote : This should be a scalable property!\r
122 \r
123   public void updateConservation()\r
124   {\r
125     Conservation cons = new jalview.analysis.Conservation("All",\r
126         jalview.schemes.ResidueProperties.propHash, 3,\r
127         alignment.getSequences(), 0,\r
128         alignment.getWidth()-1);\r
129     cons.calculate();\r
130     cons.verdict(false, ConsPercGaps);\r
131     cons.findQuality();\r
132     int alWidth = alignment.getWidth();\r
133     Annotation [] annotations = new Annotation[alWidth];\r
134     Annotation [] qannotations = new Annotation[alWidth];\r
135     String sequence = cons.getConsSequence().getSequence();\r
136     float minR,minG,minB, maxR,maxG,maxB;\r
137     minR = 0.3f;\r
138     minG = 0.0f;\r
139     minB = 0f;\r
140     maxR = 1.0f-minR; maxG=0.9f-minG; maxB=0f-minB; // scalable range for colouring both Conservation and Quality\r
141     float min = 0f;\r
142     float max = 11f;\r
143     float qmin = cons.qualityRange[0].floatValue();\r
144     float qmax = cons.qualityRange[1].floatValue();\r
145 \r
146     for (int i = 0; i < alWidth; i++)\r
147     {\r
148       float value = 0;\r
149       try\r
150         {\r
151           value = Integer.parseInt(sequence.charAt(i) + "");\r
152         }\r
153       catch (Exception ex)\r
154         {\r
155           if (sequence.charAt(i) == '*') value = 11;\r
156           if (sequence.charAt(i) == '+') value = 10;\r
157         }\r
158       float vprop = value-min;\r
159       vprop/=max;\r
160       annotations[i] = new Annotation(sequence.charAt(i) + "",\r
161                                       "", ' ', value, new Color(minR+maxR*vprop, minG+maxG*vprop, minB+maxB*vprop));\r
162       // Quality calc\r
163       value = ((Double) cons.quality.get(i)).floatValue();\r
164       vprop = value - qmin;\r
165       vprop/=qmax;\r
166       qannotations[i] = new Annotation(" ",\r
167                                       String.valueOf(value), ' ', value, new Color(minR+maxR*vprop, minG+maxG*vprop, minB+maxB*vprop));\r
168     }\r
169 \r
170     if(conservation==null)\r
171     {\r
172       conservation = new AlignmentAnnotation("Conservation",\r
173                                              "Conservation of total alignment less than "+ConsPercGaps+"% gaps",\r
174                                              annotations,\r
175                                              0f, // cons.qualityRange[0].floatValue(),\r
176                                              11f, // cons.qualityRange[1].floatValue()\r
177                                              1);\r
178       if(showConservation)\r
179       alignment.addAnnotation(conservation);\r
180       quality = new AlignmentAnnotation("Quality",\r
181                                         "Alignment Quality based on Blosum62 scores",\r
182                                         qannotations,\r
183                                         cons.qualityRange[0].floatValue(),\r
184                                         cons.qualityRange[1].floatValue(),\r
185                                         1);\r
186       if(showQuality)\r
187         alignment.addAnnotation(quality);\r
188     }\r
189     else {\r
190       conservation.annotations = annotations;\r
191       quality.annotations = qannotations;\r
192       quality.graphMax = cons.qualityRange[1].floatValue();\r
193     }\r
194 \r
195 \r
196   }\r
197 \r
198   public void updateConsensus()\r
199   {\r
200     Annotation [] annotations = new Annotation[alignment.getWidth()];\r
201 \r
202     // this routine prevents vconsensus becoming a new object each time\r
203     // consenus is calculated. Important for speed of Blosum62\r
204     // and PID colouring of alignment\r
205     if(vconsensus == null)\r
206         vconsensus = alignment.getAAFrequency();\r
207     else\r
208     {\r
209         Vector temp = alignment.getAAFrequency();\r
210         vconsensus.clear();\r
211         Enumeration e = temp.elements();\r
212         while(e.hasMoreElements())\r
213         {\r
214           vconsensus.add(e.nextElement());\r
215         }\r
216     }\r
217     Hashtable hash = null;\r
218     for (int i = 0; i<alignment.getWidth(); i++)\r
219     {\r
220         hash = (Hashtable) vconsensus.elementAt(i);\r
221         float value = Float.parseFloat(hash.get("maxCount").toString());\r
222         value /= Float.parseFloat(hash.get("size").toString());\r
223 \r
224         value *= 100;\r
225         String maxRes = hash.get("maxResidue")+" ";\r
226         String mouseOver = hash.get("maxResidue")+" ";\r
227         if(maxRes.length()>2)\r
228         {\r
229           mouseOver = "["+maxRes+"] ";\r
230           maxRes = "+ ";\r
231         }\r
232 \r
233         mouseOver += (int)value+"%";\r
234         annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);\r
235 \r
236     }\r
237 \r
238      if(consensus==null)\r
239      {\r
240        consensus = new AlignmentAnnotation("Consensus",\r
241                                            "PID", annotations, 0f, 100f, 1);\r
242        if(showIdentity)\r
243          alignment.addAnnotation(consensus);\r
244      }\r
245      else\r
246        consensus.annotations = annotations;\r
247 \r
248   }\r
249 \r
250 \r
251   public SequenceGroup getSelectionGroup()\r
252   {\r
253     return selectionGroup;\r
254   }\r
255 \r
256   public void setSelectionGroup(SequenceGroup sg)\r
257   {\r
258     selectionGroup = sg;\r
259   }\r
260 \r
261 \r
262  public boolean getConservationSelected()\r
263  {\r
264    return conservationColourSelected;\r
265  }\r
266 \r
267  public void setConservationSelected(boolean b)\r
268  {\r
269    conservationColourSelected = b;\r
270  }\r
271 \r
272  public boolean getAbovePIDThreshold()\r
273  {\r
274    return abovePIDThreshold;\r
275  }\r
276 \r
277  public void setAbovePIDThreshold(boolean b)\r
278  {\r
279    abovePIDThreshold = b;\r
280  }\r
281 \r
282   public int getStartRes() {\r
283     return startRes;\r
284   }\r
285 \r
286   public int getEndRes() {\r
287     return endRes;\r
288   }\r
289 \r
290   public int getStartSeq() {\r
291     return startSeq;\r
292   }\r
293 \r
294   public void setGlobalColourScheme(ColourSchemeI cs)\r
295   {\r
296      globalColourScheme = cs;\r
297   }\r
298 \r
299   public ColourSchemeI getGlobalColourScheme()\r
300   {\r
301     return globalColourScheme;\r
302   }\r
303 \r
304 \r
305   public void setStartRes(int res) {\r
306     this.startRes = res;\r
307   }\r
308   public void setStartSeq(int seq) {\r
309     this.startSeq = seq;\r
310   }\r
311   public void setEndRes(int res) {\r
312     if (res > alignment.getWidth()-1) {\r
313       // log.System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));\r
314        res = alignment.getWidth()-1;\r
315     }\r
316     if (res < 0) {\r
317       res = 0;\r
318     }\r
319     this.endRes = res;\r
320   }\r
321   public void setEndSeq(int seq) {\r
322     if (seq > alignment.getHeight()) {\r
323       seq = alignment.getHeight();\r
324     }\r
325     if (seq < 0) {\r
326       seq = 0;\r
327     }\r
328     this.endSeq = seq;\r
329   }\r
330   public int getEndSeq() {\r
331     return endSeq;\r
332   }\r
333 \r
334   public void setFont(Font f) {\r
335     font = f;\r
336     javax.swing.JFrame temp = new javax.swing.JFrame();\r
337     temp.addNotify();\r
338     java.awt.FontMetrics fm = temp.getGraphics().getFontMetrics(font);\r
339     setCharHeight(fm.getHeight());\r
340     setCharWidth(fm.charWidth('M'));\r
341   }\r
342 \r
343   public Font getFont() {\r
344     return font;\r
345   }\r
346   public void setCharWidth(int w) {\r
347     this.charWidth = w;\r
348   }\r
349   public int getCharWidth() {\r
350     return charWidth;\r
351   }\r
352   public void setCharHeight(int h) {\r
353     this.charHeight = h;\r
354   }\r
355   public int getCharHeight() {\r
356     return charHeight;\r
357   }\r
358   public void setChunkWidth(int w) {\r
359     this.chunkWidth = w;\r
360   }\r
361   public int getChunkWidth() {\r
362     return chunkWidth;\r
363   }\r
364   public void setChunkHeight(int h) {\r
365     this.chunkHeight = h;\r
366   }\r
367   public int getChunkHeight() {\r
368     return chunkHeight;\r
369   }\r
370   public AlignmentI getAlignment() {\r
371     return alignment;\r
372   }\r
373   public void setAlignment(AlignmentI align) {\r
374     this.alignment = align;\r
375   }\r
376 \r
377   public void setWrapAlignment(boolean state) {\r
378     wrapAlignment = state;\r
379   }\r
380   public void setShowText(boolean state) {\r
381     showText = state;\r
382   }\r
383 \r
384   public void setRenderGaps(boolean state){\r
385     renderGaps = state;\r
386   }\r
387 \r
388 \r
389   public boolean getColourText()\r
390   {\r
391     return showColourText;\r
392   }\r
393 \r
394   public void setColourText(boolean state)\r
395   {\r
396     showColourText = state;\r
397   }\r
398 \r
399   public void setShowBoxes(boolean state) {\r
400     showBoxes = state;\r
401   }\r
402 \r
403   public boolean getWrapAlignment() {\r
404       return wrapAlignment;\r
405   }\r
406   public boolean getShowText() {\r
407     return showText;\r
408   }\r
409   public boolean getShowBoxes() {\r
410     return showBoxes;\r
411   }\r
412 \r
413   public char getGapCharacter() {\r
414     return getAlignment().getGapCharacter();\r
415   }\r
416   public void setGapCharacter(char gap) {\r
417     if (getAlignment() != null) {\r
418       getAlignment().setGapCharacter(gap);\r
419     }\r
420   }\r
421   public void setThreshold(int thresh) {\r
422     threshold = thresh;\r
423   }\r
424   public int getThreshold() {\r
425     return threshold;\r
426   }\r
427   public void setIncrement(int inc) {\r
428     increment = inc;\r
429   }\r
430   public int getIncrement() {\r
431     return increment;\r
432   }\r
433   public int getIndex(int y) {\r
434     int y1     = 0;\r
435     int starty = getStartSeq();\r
436     int endy   = getEndSeq();\r
437 \r
438     for (int i = starty; i <= endy; i++) {\r
439       if (i < alignment.getHeight() && alignment.getSequenceAt(i) != null) {\r
440         int y2 = y1 + getCharHeight();\r
441 \r
442         if (y>=y1 && y <=y2) {\r
443           return i;\r
444         }\r
445         y1  = y2;\r
446       } else {\r
447         return -1;\r
448       }\r
449     }\r
450     return -1;\r
451   }\r
452 \r
453   public ColumnSelection getColumnSelection() {\r
454     return colSel;\r
455   }\r
456 \r
457   public void resetSeqLimits(int height) {\r
458     setEndSeq(height/getCharHeight());\r
459   }\r
460   public void setCurrentTree(NJTree tree) {\r
461       currentTree = tree;\r
462   }\r
463   public NJTree getCurrentTree() {\r
464     return currentTree;\r
465   }\r
466 \r
467   public void setColourAppliesToAllGroups(boolean b)\r
468   {   colourAppliesToAllGroups = b; }\r
469 \r
470   public boolean getColourAppliesToAllGroups()\r
471   {return colourAppliesToAllGroups; }\r
472 \r
473   public boolean getShowFullId()\r
474   {\r
475     return showFullId;\r
476   }\r
477 \r
478   public void setShowFullId(boolean b)\r
479   {\r
480     showFullId = b;\r
481   }\r
482 \r
483   public boolean getShowAnnotation()\r
484   {   return showAnnotation;  }\r
485 \r
486   public void setShowAnnotation(boolean b)\r
487   {    showAnnotation = b;  }\r
488 \r
489   public boolean getScaleAboveWrapped()\r
490   { return scaleAboveWrapped;}\r
491 \r
492   public boolean getScaleLeftWrapped()\r
493   { return scaleLeftWrapped; }\r
494 \r
495   public boolean getScaleRightWrapped()\r
496   { return scaleRightWrapped; }\r
497 \r
498   public void setScaleAboveWrapped(boolean b)\r
499   { scaleAboveWrapped = b; }\r
500 \r
501   public void setScaleLeftWrapped(boolean b)\r
502   { scaleLeftWrapped = b; }\r
503 \r
504   public void setScaleRightWrapped(boolean b)\r
505   { scaleRightWrapped = b; }\r
506   // JBPNote Prolly only need this in the applet version.\r
507   private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(this);\r
508   public void addPropertyChangeListener(java.beans.PropertyChangeListener listener) {\r
509     changeSupport.addPropertyChangeListener(listener);\r
510   }\r
511 \r
512   public void removePropertyChangeListener(java.beans.PropertyChangeListener listener) {\r
513     changeSupport.removePropertyChangeListener(listener);\r
514   }\r
515   public void firePropertyChange(String prop, Object oldvalue, Object newvalue) {\r
516     changeSupport.firePropertyChange(prop, oldvalue, newvalue);\r
517   }\r
518 }\r