Colours in viewport
[jalview.git] / src / jalview / appletgui / AlignViewport.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 \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 \r
40   boolean cursorMode = false;\r
41 \r
42   boolean showJVSuffix = true;\r
43   boolean showText = true;\r
44   boolean showColourText = false;\r
45   boolean showBoxes = true;\r
46   boolean wrapAlignment = false;\r
47   boolean renderGaps = true;\r
48   boolean showSequenceFeatures = false;\r
49   boolean showAnnotation = true;\r
50   boolean showConservation = true;\r
51   boolean showQuality = true;\r
52   boolean showConsensus = true;\r
53   boolean upperCasebold = false;\r
54 \r
55   boolean colourAppliesToAllGroups = true;\r
56   ColourSchemeI globalColourScheme = null;\r
57   boolean conservationColourSelected = false;\r
58   boolean abovePIDThreshold = false;\r
59 \r
60   SequenceGroup selectionGroup;\r
61 \r
62   int charHeight;\r
63   int charWidth;\r
64   int wrappedWidth;\r
65 \r
66   Font font = new Font("SansSerif", Font.PLAIN, 10);\r
67   boolean validCharWidth = true;\r
68   AlignmentI alignment;\r
69 \r
70   ColumnSelection colSel = new ColumnSelection();\r
71 \r
72   int threshold;\r
73   int increment;\r
74 \r
75   NJTree currentTree = null;\r
76 \r
77   boolean scaleAboveWrapped = true;\r
78   boolean scaleLeftWrapped = true;\r
79   boolean scaleRightWrapped = true;\r
80 \r
81   // The following vector holds the features which are\r
82  // currently visible, in the correct order or rendering\r
83   public Hashtable featuresDisplayed;\r
84 \r
85   boolean hasHiddenColumns = false;\r
86   boolean hasHiddenRows = false;\r
87   boolean showHiddenMarkers = true;\r
88 \r
89 \r
90   public Hashtable [] hconsensus;\r
91   AlignmentAnnotation consensus;\r
92   AlignmentAnnotation conservation;\r
93   AlignmentAnnotation quality;\r
94 \r
95   boolean autocalculateConsensus = true;\r
96 \r
97   public int ConsPercGaps = 25; // JBPNote : This should be a scalable property!\r
98 \r
99   private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(this);\r
100 \r
101   boolean ignoreGapsInConsensusCalculation = false;\r
102 \r
103   jalview.bin.JalviewLite applet;\r
104 \r
105   Hashtable sequenceColours;\r
106 \r
107   boolean MAC = false;\r
108 \r
109   public AlignViewport(AlignmentI al, JalviewLite applet)\r
110   {\r
111     this.applet = applet;\r
112     setAlignment(al);\r
113     this.startRes = 0;\r
114     this.endRes = al.getWidth() - 1;\r
115     this.startSeq = 0;\r
116     this.endSeq = al.getHeight() - 1;\r
117     setFont(font);\r
118 \r
119     if(System.getProperty("os.name").startsWith("Mac"))\r
120       MAC = true;\r
121 \r
122     if (applet != null)\r
123     {\r
124       String param = applet.getParameter("showFullId");\r
125       if (param != null)\r
126       {\r
127         showJVSuffix = Boolean.valueOf(param).booleanValue();\r
128       }\r
129 \r
130       param = applet.getParameter("showAnnotation");\r
131       if (param != null)\r
132       {\r
133         showAnnotation = Boolean.valueOf(param).booleanValue();\r
134       }\r
135 \r
136       param = applet.getParameter("showConservation");\r
137       if (param != null)\r
138       {\r
139         showConservation = Boolean.valueOf(param).booleanValue();\r
140       }\r
141 \r
142       param = applet.getParameter("showQuality");\r
143       if (param != null)\r
144       {\r
145         showQuality = Boolean.valueOf(param).booleanValue();\r
146       }\r
147 \r
148       param = applet.getParameter("showConsensus");\r
149       if (param != null)\r
150       {\r
151         showConsensus = Boolean.valueOf(param).booleanValue();\r
152       }\r
153 \r
154       param = applet.getParameter("upperCase");\r
155       if (param != null)\r
156       {\r
157         if(param.equalsIgnoreCase("bold"))\r
158           upperCasebold = true;\r
159       }\r
160 \r
161     }\r
162     // We must set conservation and consensus before setting colour,\r
163     // as Blosum and Clustal require this to be done\r
164     updateConservation();\r
165     updateConsensus();\r
166 \r
167 \r
168     if (applet != null)\r
169     {\r
170       String colour = applet.getParameter("defaultColour");\r
171 \r
172       if(colour == null)\r
173       {\r
174         colour = applet.getParameter("userDefinedColour");\r
175         if(colour !=null)\r
176           colour = "User Defined";\r
177       }\r
178 \r
179       if(colour != null)\r
180       {\r
181         globalColourScheme = ColourSchemeProperty.getColour(alignment, colour);\r
182         if (globalColourScheme != null)\r
183         {\r
184           globalColourScheme.setConsensus(hconsensus);\r
185         }\r
186       }\r
187 \r
188       if(applet.getParameter("userDefinedColour")!=null)\r
189       {\r
190         ((UserColourScheme)globalColourScheme).parseAppletParameter(\r
191             applet.getParameter("userDefinedColour"));\r
192       }\r
193 \r
194 \r
195     }\r
196   }\r
197 \r
198   public void showSequenceFeatures(boolean b)\r
199   {\r
200     showSequenceFeatures = b;\r
201   }\r
202 \r
203   public boolean getShowSequenceFeatures()\r
204   {\r
205     return showSequenceFeatures;\r
206   }\r
207 \r
208 \r
209   public void updateConservation()\r
210   {\r
211     if(alignment.isNucleotide())\r
212           return;\r
213 \r
214     Conservation cons = new jalview.analysis.Conservation("All",\r
215         jalview.schemes.ResidueProperties.propHash, 3,\r
216         alignment.getSequences(), 0,\r
217         alignment.getWidth() - 1);\r
218     cons.calculate();\r
219     cons.verdict(false, ConsPercGaps);\r
220     cons.findQuality();\r
221     int alWidth = alignment.getWidth();\r
222     Annotation[] annotations = new Annotation[alWidth];\r
223     Annotation[] qannotations = new Annotation[alWidth];\r
224     String sequence = cons.getConsSequence().getSequence();\r
225     float minR, minG, minB, maxR, maxG, maxB;\r
226     minR = 0.3f;\r
227     minG = 0.0f;\r
228     minB = 0f;\r
229     maxR = 1.0f - minR;\r
230     maxG = 0.9f - minG;\r
231     maxB = 0f - minB; // scalable range for colouring both Conservation and Quality\r
232     float min = 0f;\r
233     float max = 11f;\r
234     float qmin = cons.qualityRange[0].floatValue();\r
235     float qmax = cons.qualityRange[1].floatValue();\r
236 \r
237     for (int i = 0; i < alWidth; i++)\r
238     {\r
239       float value = 0;\r
240       try\r
241       {\r
242         value = Integer.parseInt(sequence.charAt(i) + "");\r
243       }\r
244       catch (Exception ex)\r
245       {\r
246         if (sequence.charAt(i) == '*')\r
247         {\r
248           value = 11;\r
249         }\r
250         if (sequence.charAt(i) == '+')\r
251         {\r
252           value = 10;\r
253         }\r
254       }\r
255       float vprop = value - min;\r
256       vprop /= max;\r
257 \r
258       annotations[i] = new Annotation(sequence.charAt(i) + "",\r
259                                       "", ' ', value,\r
260                                       new Color(minR + maxR * vprop,\r
261                                                 minG + maxG * vprop,\r
262                                                 minB + maxB * vprop));\r
263       // Quality calc\r
264       value = ( (Double) cons.quality.elementAt(i)).floatValue();\r
265       vprop = value - qmin;\r
266       vprop /= qmax;\r
267       qannotations[i] = new Annotation(" ",\r
268                                        String.valueOf(value), ' ', value,\r
269                                        new\r
270                                        Color(minR + maxR * vprop,\r
271                                              minG + maxG * vprop,\r
272                                              minB + maxB * vprop));\r
273     }\r
274 \r
275     if (conservation == null)\r
276     {\r
277       conservation = new AlignmentAnnotation("Conservation",\r
278                                              "Conservation of total alignment less than " +\r
279                                              ConsPercGaps + "% gaps",\r
280                                              annotations,\r
281                                              0f, // cons.qualityRange[0].floatValue(),\r
282                                              11f, // cons.qualityRange[1].floatValue()\r
283                                              AlignmentAnnotation.BAR_GRAPH);\r
284       if (showConservation)\r
285       {\r
286         alignment.addAnnotation(conservation);\r
287       }\r
288       quality = new AlignmentAnnotation("Quality",\r
289                                         "Alignment Quality based on Blosum62 scores",\r
290                                         qannotations,\r
291                                         cons.qualityRange[0].floatValue(),\r
292                                         cons.qualityRange[1].floatValue(),\r
293                                         AlignmentAnnotation.BAR_GRAPH);\r
294       if (showQuality)\r
295       {\r
296         alignment.addAnnotation(quality);\r
297       }\r
298     }\r
299     else\r
300     {\r
301       conservation.annotations = annotations;\r
302       quality.annotations = qannotations;\r
303       quality.graphMax = cons.qualityRange[1].floatValue();\r
304     }\r
305 \r
306   }\r
307 \r
308   public void updateConsensus()\r
309   {\r
310     // this routine prevents vconsensus becoming a new object each time\r
311     // consenus is calculated. Important for speed of Blosum62\r
312     // and PID colouring of alignment\r
313     int aWidth = alignment.getWidth();\r
314 \r
315     Annotation[] annotations = new Annotation[aWidth];\r
316 \r
317     hconsensus = new Hashtable[aWidth];\r
318     AAFrequency.calculate(alignment.getSequencesArray(),\r
319                           0, aWidth,\r
320                           hconsensus);\r
321 \r
322     for (int i = 0; i < aWidth; i++)\r
323     {\r
324       float value = 0;\r
325       if(ignoreGapsInConsensusCalculation)\r
326         value = ((Float)hconsensus[i].get(AAFrequency.PID_NOGAPS)).floatValue();\r
327       else\r
328         value = ((Float)hconsensus[i].get(AAFrequency.PID_GAPS)).floatValue();\r
329 \r
330       String maxRes = hconsensus[i].get(AAFrequency.MAXRESIDUE).toString();\r
331       String mouseOver = maxRes;\r
332       if (maxRes.length() > 1)\r
333       {\r
334         mouseOver = "[" + maxRes + "] ";\r
335         maxRes = "+";\r
336       }\r
337 \r
338 \r
339       mouseOver += (int) value + "%";\r
340       annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);\r
341 \r
342     }\r
343 \r
344     if (consensus == null)\r
345     {\r
346       consensus = new AlignmentAnnotation("Consensus",\r
347                                           "PID", annotations, 0f, 100f, AlignmentAnnotation.BAR_GRAPH);\r
348       if (showConsensus)\r
349       {\r
350         alignment.addAnnotation(consensus);\r
351       }\r
352     }\r
353     else\r
354     {\r
355       consensus.annotations = annotations;\r
356     }\r
357 \r
358     if(globalColourScheme!=null)\r
359           globalColourScheme.setConsensus(hconsensus);\r
360 \r
361   }\r
362   /**\r
363    * get the consensus sequence as displayed under the PID consensus annotation row.\r
364    * @return consensus sequence as a new sequence object\r
365    */\r
366   /**\r
367    * get the consensus sequence as displayed under the PID consensus annotation row.\r
368    * @return consensus sequence as a new sequence object\r
369    */\r
370   public SequenceI getConsensusSeq() {\r
371     if (consensus==null)\r
372       updateConsensus();\r
373     if (consensus==null)\r
374       return null;\r
375     StringBuffer seqs=new StringBuffer();\r
376     for (int i=0; i<consensus.annotations.length; i++) {\r
377       if (consensus.annotations[i]!=null) {\r
378         if (consensus.annotations[i].description.charAt(0) == '[')\r
379           seqs.append(consensus.annotations[i].description.charAt(1));\r
380         else\r
381           seqs.append(consensus.annotations[i].displayCharacter);\r
382       }\r
383     }\r
384     SequenceI sq = new Sequence("Consensus", seqs.toString());\r
385     sq.setDescription("Percentage Identity Consensus "+((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));\r
386     return sq;\r
387   }\r
388   public SequenceGroup getSelectionGroup()\r
389   {\r
390     return selectionGroup;\r
391   }\r
392 \r
393   public void setSelectionGroup(SequenceGroup sg)\r
394   {\r
395     selectionGroup = sg;\r
396   }\r
397 \r
398   public boolean getConservationSelected()\r
399   {\r
400     return conservationColourSelected;\r
401   }\r
402 \r
403   public void setConservationSelected(boolean b)\r
404   {\r
405     conservationColourSelected = b;\r
406   }\r
407 \r
408   public boolean getAbovePIDThreshold()\r
409   {\r
410     return abovePIDThreshold;\r
411   }\r
412 \r
413   public void setAbovePIDThreshold(boolean b)\r
414   {\r
415     abovePIDThreshold = b;\r
416   }\r
417 \r
418   public int getStartRes()\r
419   {\r
420     return startRes;\r
421   }\r
422 \r
423   public int getEndRes()\r
424   {\r
425     return endRes;\r
426   }\r
427 \r
428   public int getStartSeq()\r
429   {\r
430     return startSeq;\r
431   }\r
432 \r
433   public void setGlobalColourScheme(ColourSchemeI cs)\r
434   {\r
435     globalColourScheme = cs;\r
436   }\r
437 \r
438   public ColourSchemeI getGlobalColourScheme()\r
439   {\r
440     return globalColourScheme;\r
441   }\r
442 \r
443   public void setStartRes(int res)\r
444   {\r
445     this.startRes = res;\r
446   }\r
447 \r
448   public void setStartSeq(int seq)\r
449   {\r
450     this.startSeq = seq;\r
451   }\r
452 \r
453   public void setEndRes(int res)\r
454   {\r
455     if (res > alignment.getWidth() - 1)\r
456     {\r
457       // log.System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));\r
458       res = alignment.getWidth() - 1;\r
459     }\r
460     if (res < 0)\r
461     {\r
462       res = 0;\r
463     }\r
464     this.endRes = res;\r
465   }\r
466 \r
467   public void setEndSeq(int seq)\r
468   {\r
469     if (seq > alignment.getHeight())\r
470     {\r
471       seq = alignment.getHeight();\r
472     }\r
473     if (seq < 0)\r
474     {\r
475       seq = 0;\r
476     }\r
477     this.endSeq = seq;\r
478   }\r
479 \r
480   public int getEndSeq()\r
481   {\r
482     return endSeq;\r
483   }\r
484 \r
485   java.awt.Frame nullFrame;\r
486   public void setFont(Font f)\r
487   {\r
488     font = f;\r
489     if(nullFrame == null)\r
490     {\r
491       nullFrame = new java.awt.Frame();\r
492       nullFrame.addNotify();\r
493     }\r
494 \r
495     java.awt.FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);\r
496     setCharHeight(fm.getHeight());\r
497     charWidth = fm.charWidth('M');\r
498 \r
499     if(upperCasebold)\r
500     {\r
501       Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());\r
502       fm = nullFrame.getGraphics().getFontMetrics(f2);\r
503       charWidth = fm.stringWidth("MMMMMMMMMMM") / 10;\r
504     }\r
505   }\r
506 \r
507   public Font getFont()\r
508   {\r
509     return font;\r
510   }\r
511 \r
512   public int getCharWidth()\r
513   {\r
514     return charWidth;\r
515   }\r
516 \r
517   public void setCharHeight(int h)\r
518   {\r
519     this.charHeight = h;\r
520   }\r
521 \r
522   public int getCharHeight()\r
523   {\r
524     return charHeight;\r
525   }\r
526 \r
527   public void setWrappedWidth(int w)\r
528   {\r
529     this.wrappedWidth = w;\r
530   }\r
531 \r
532   public int getwrappedWidth()\r
533   {\r
534     return wrappedWidth;\r
535   }\r
536 \r
537   public AlignmentI getAlignment()\r
538   {\r
539     return alignment;\r
540   }\r
541 \r
542   public void setAlignment(AlignmentI align)\r
543   {\r
544     this.alignment = align;\r
545   }\r
546 \r
547   public void setWrapAlignment(boolean state)\r
548   {\r
549     wrapAlignment = state;\r
550   }\r
551 \r
552   public void setShowText(boolean state)\r
553   {\r
554     showText = state;\r
555   }\r
556 \r
557   public void setRenderGaps(boolean state)\r
558   {\r
559     renderGaps = state;\r
560   }\r
561 \r
562   public boolean getColourText()\r
563   {\r
564     return showColourText;\r
565   }\r
566 \r
567   public void setColourText(boolean state)\r
568   {\r
569     showColourText = state;\r
570   }\r
571 \r
572   public void setShowBoxes(boolean state)\r
573   {\r
574     showBoxes = state;\r
575   }\r
576 \r
577   public boolean getWrapAlignment()\r
578   {\r
579     return wrapAlignment;\r
580   }\r
581 \r
582   public boolean getShowText()\r
583   {\r
584     return showText;\r
585   }\r
586 \r
587   public boolean getShowBoxes()\r
588   {\r
589     return showBoxes;\r
590   }\r
591 \r
592   public char getGapCharacter()\r
593   {\r
594     return getAlignment().getGapCharacter();\r
595   }\r
596 \r
597   public void setGapCharacter(char gap)\r
598   {\r
599     if (getAlignment() != null)\r
600     {\r
601       getAlignment().setGapCharacter(gap);\r
602     }\r
603   }\r
604 \r
605   public void setThreshold(int thresh)\r
606   {\r
607     threshold = thresh;\r
608   }\r
609 \r
610   public int getThreshold()\r
611   {\r
612     return threshold;\r
613   }\r
614 \r
615   public void setIncrement(int inc)\r
616   {\r
617     increment = inc;\r
618   }\r
619 \r
620   public int getIncrement()\r
621   {\r
622     return increment;\r
623   }\r
624 \r
625   public void setHiddenColumns(ColumnSelection colsel)\r
626   {\r
627     this.colSel = colsel;\r
628     if(colSel.getHiddenColumns()!=null)\r
629       hasHiddenColumns = true;\r
630   }\r
631 \r
632   public ColumnSelection getColumnSelection()\r
633   {\r
634     return colSel;\r
635   }\r
636 \r
637   public void resetSeqLimits(int height)\r
638   {\r
639     setEndSeq(height / getCharHeight());\r
640   }\r
641 \r
642   public void setCurrentTree(NJTree tree)\r
643   {\r
644     currentTree = tree;\r
645   }\r
646 \r
647   public NJTree getCurrentTree()\r
648   {\r
649     return currentTree;\r
650   }\r
651 \r
652   public void setColourAppliesToAllGroups(boolean b)\r
653   {\r
654     colourAppliesToAllGroups = b;\r
655   }\r
656 \r
657   public boolean getColourAppliesToAllGroups()\r
658   {\r
659     return colourAppliesToAllGroups;\r
660   }\r
661 \r
662   public boolean getShowJVSuffix()\r
663   {\r
664     return showJVSuffix;\r
665   }\r
666 \r
667   public void setShowJVSuffix(boolean b)\r
668   {\r
669     showJVSuffix = b;\r
670   }\r
671 \r
672   public boolean getShowAnnotation()\r
673   {\r
674     return showAnnotation;\r
675   }\r
676 \r
677   public void setShowAnnotation(boolean b)\r
678   {\r
679     showAnnotation = b;\r
680   }\r
681 \r
682   public boolean getScaleAboveWrapped()\r
683   {\r
684     return scaleAboveWrapped;\r
685   }\r
686 \r
687   public boolean getScaleLeftWrapped()\r
688   {\r
689     return scaleLeftWrapped;\r
690   }\r
691 \r
692   public boolean getScaleRightWrapped()\r
693   {\r
694     return scaleRightWrapped;\r
695   }\r
696 \r
697   public void setScaleAboveWrapped(boolean b)\r
698   {\r
699     scaleAboveWrapped = b;\r
700   }\r
701 \r
702   public void setScaleLeftWrapped(boolean b)\r
703   {\r
704     scaleLeftWrapped = b;\r
705   }\r
706 \r
707   public void setScaleRightWrapped(boolean b)\r
708   {\r
709     scaleRightWrapped = b;\r
710   }\r
711 \r
712   public void setIgnoreGapsConsensus(boolean b)\r
713   {\r
714     ignoreGapsInConsensusCalculation = b;\r
715     updateConsensus();\r
716     if (globalColourScheme!=null)\r
717     {\r
718       globalColourScheme.setThreshold(globalColourScheme.getThreshold(),\r
719           ignoreGapsInConsensusCalculation);\r
720 \r
721     }\r
722   }\r
723 \r
724   /**\r
725    * Property change listener for changes in alignment\r
726    *\r
727    * @param listener DOCUMENT ME!\r
728    */\r
729   public void addPropertyChangeListener(\r
730       java.beans.PropertyChangeListener listener)\r
731   {\r
732       changeSupport.addPropertyChangeListener(listener);\r
733   }\r
734 \r
735   /**\r
736    * DOCUMENT ME!\r
737    *\r
738    * @param listener DOCUMENT ME!\r
739    */\r
740   public void removePropertyChangeListener(\r
741       java.beans.PropertyChangeListener listener)\r
742   {\r
743       changeSupport.removePropertyChangeListener(listener);\r
744   }\r
745 \r
746   /**\r
747    * Property change listener for changes in alignment\r
748    *\r
749    * @param prop DOCUMENT ME!\r
750    * @param oldvalue DOCUMENT ME!\r
751    * @param newvalue DOCUMENT ME!\r
752    */\r
753   public void firePropertyChange(String prop, Object oldvalue, Object newvalue)\r
754   {\r
755       changeSupport.firePropertyChange(prop, oldvalue, newvalue);\r
756   }\r
757 \r
758 \r
759 \r
760   public boolean getIgnoreGapsConsensus()\r
761   {\r
762     return ignoreGapsInConsensusCalculation;\r
763   }\r
764   public void hideSelectedColumns()\r
765   {\r
766     if (colSel.size() < 1)\r
767       return;\r
768 \r
769     colSel.hideSelectedColumns();\r
770     setSelectionGroup(null);\r
771 \r
772     hasHiddenColumns = true;\r
773   }\r
774 \r
775   public void invertColumnSelection()\r
776   {\r
777     int column;\r
778     for (int i = 0; i < alignment.getWidth(); i++)\r
779     {\r
780       column = i;\r
781 \r
782       if (colSel.contains(column))\r
783         colSel.removeElement(column);\r
784       else\r
785         colSel.addElement(column);\r
786 \r
787     }\r
788   }\r
789 \r
790 \r
791   public void hideColumns(int start, int end)\r
792   {\r
793     if(start==end)\r
794       colSel.hideColumns(start);\r
795     else\r
796       colSel.hideColumns(start, end);\r
797 \r
798     hasHiddenColumns = true;\r
799   }\r
800 \r
801   public void hideAllSelectedSeqs()\r
802   {\r
803     if (selectionGroup == null)\r
804       return;\r
805 \r
806     SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);\r
807 \r
808     hideSequence(seqs);\r
809 \r
810     setSelectionGroup(null);\r
811   }\r
812 \r
813   public void hideSequence(SequenceI [] seq)\r
814   {\r
815     if(seq!=null)\r
816     {\r
817       for (int i = 0; i < seq.length; i++)\r
818         alignment.getHiddenSequences().hideSequence(seq[i]);\r
819 \r
820       hasHiddenRows = true;\r
821       firePropertyChange("alignment", null, alignment.getSequences());\r
822     }\r
823   }\r
824 \r
825   public void showColumn(int col)\r
826   {\r
827     colSel.revealHiddenColumns(col);\r
828     if(colSel.getHiddenColumns()==null)\r
829       hasHiddenColumns = false;\r
830   }\r
831 \r
832   public void showAllHiddenColumns()\r
833   {\r
834     colSel.revealAllHiddenColumns();\r
835     hasHiddenColumns = false;\r
836   }\r
837 \r
838   public void showAllHiddenSeqs()\r
839   {\r
840     if(alignment.getHiddenSequences().getSize()>0)\r
841     {\r
842       if(selectionGroup==null)\r
843       {\r
844         selectionGroup = new SequenceGroup();\r
845         selectionGroup.setEndRes(alignment.getWidth()-1);\r
846       }\r
847       Vector tmp = alignment.getHiddenSequences().showAll();\r
848       for(int t=0; t<tmp.size(); t++)\r
849       {\r
850         selectionGroup.addSequence(\r
851             (SequenceI)tmp.elementAt(t), false\r
852             );\r
853       }\r
854       firePropertyChange("alignment", null, alignment.getSequences());\r
855       hasHiddenRows = false;\r
856     }\r
857   }\r
858 \r
859   public int adjustForHiddenSeqs(int alignmentIndex)\r
860   {\r
861     return alignment.getHiddenSequences().adjustForHiddenSeqs(alignmentIndex);\r
862   }\r
863 \r
864   /**\r
865    * This method returns the a new SequenceI [] with\r
866    * the selection sequence and start and end points adjusted\r
867    * @return String[]\r
868    */\r
869   public SequenceI[] getSelectionAsNewSequence()\r
870   {\r
871     SequenceI[] sequences;\r
872 \r
873     if (selectionGroup == null)\r
874       sequences = alignment.getSequencesArray();\r
875     else\r
876       sequences = selectionGroup.getSelectionAsNewSequences(alignment);\r
877 \r
878     return sequences;\r
879   }\r
880 \r
881   /**\r
882    * This method returns the visible alignment as text, as\r
883    * seen on the GUI, ie if columns are hidden they will not\r
884    * be returned in the result.\r
885    * Use this for calculating trees, PCA, redundancy etc on views\r
886    * which contain hidden columns.\r
887    * @return String[]\r
888    */\r
889   public jalview.datamodel.CigarArray getViewAsCigars(boolean selectedRegionOnly)\r
890   {\r
891     CigarArray selection=null;\r
892     SequenceI [] seqs= null;\r
893     int i, iSize;\r
894     int start = 0, end = 0;\r
895     if(selectedRegionOnly && selectionGroup!=null)\r
896     {\r
897       iSize = selectionGroup.getSize(false);\r
898       seqs = selectionGroup.getSequencesInOrder(alignment);\r
899       start = selectionGroup.getStartRes();\r
900       end = selectionGroup.getEndRes(); // inclusive for start and end in SeqCigar constructor\r
901     }\r
902     else\r
903     {\r
904       iSize = alignment.getHeight();\r
905       seqs = alignment.getSequencesArray();\r
906       end = alignment.getWidth()-1;\r
907     }\r
908     SeqCigar[] selseqs = new SeqCigar[iSize];\r
909     for(i=0; i<iSize; i++)\r
910     {\r
911       selseqs[i] = new SeqCigar(seqs[i], start, end);\r
912     }\r
913     selection=new CigarArray(selseqs);\r
914     // now construct the CigarArray operations\r
915     if (hasHiddenColumns) {\r
916       Vector regions = colSel.getHiddenColumns();\r
917       int [] region;\r
918       int hideStart, hideEnd;\r
919       int last=start;\r
920       for (int j = 0; last<end & j < regions.size(); j++)\r
921       {\r
922         region = (int[]) regions.elementAt(j);\r
923         hideStart = region[0];\r
924         hideEnd = region[1];\r
925         // edit hidden regions to selection range\r
926         if(hideStart<last) {\r
927           if (hideEnd > last)\r
928           {\r
929             hideStart = last;\r
930           } else\r
931             continue;\r
932         }\r
933 \r
934         if (hideStart>end)\r
935           break;\r
936 \r
937         if (hideEnd>end)\r
938           hideEnd=end;\r
939 \r
940         if (hideStart>hideEnd)\r
941           break;\r
942         /**\r
943          * form operations...\r
944          */\r
945         if (last<hideStart)\r
946           selection.addOperation(CigarArray.M, hideStart-last);\r
947         selection.addOperation(CigarArray.D, 1+hideEnd-hideStart);\r
948         last = hideEnd+1;\r
949       }\r
950       // Final match if necessary.\r
951       if (last<end)\r
952         selection.addOperation(CigarArray.M, end-last+1);\r
953     } else {\r
954       selection.addOperation(CigarArray.M, end-start+1);\r
955     }\r
956     return selection;\r
957   }\r
958   /**\r
959    * return a compact representation of the current alignment selection to\r
960    * pass to an analysis function\r
961    * @param selectedOnly boolean true to just return the selected view\r
962    * @return AlignmentView\r
963    */\r
964   jalview.datamodel.AlignmentView getAlignmentView(boolean selectedOnly) {\r
965     // JBPNote:\r
966     // this is here because the AlignmentView constructor modifies the CigarArray\r
967     // object. Refactoring of Cigar and alignment view representation should\r
968     // be done to remove redundancy.\r
969     CigarArray aligview = getViewAsCigars(selectedOnly);\r
970     if (aligview!=null) {\r
971       return new AlignmentView(aligview,\r
972           (selectedOnly && selectionGroup!=null) ? selectionGroup.getStartRes() : 0);\r
973     }\r
974     return null;\r
975   }\r
976   /**\r
977    * This method returns the visible alignment as text, as\r
978    * seen on the GUI, ie if columns are hidden they will not\r
979    * be returned in the result.\r
980    * Use this for calculating trees, PCA, redundancy etc on views\r
981    * which contain hidden columns.\r
982    * @return String[]\r
983    */\r
984   public String [] getViewAsString(boolean selectedRegionOnly)\r
985   {\r
986     String [] selection = null;\r
987     SequenceI [] seqs= null;\r
988     int i, iSize;\r
989     int start = 0, end = 0;\r
990     if(selectedRegionOnly && selectionGroup!=null)\r
991     {\r
992       iSize = selectionGroup.getSize(false);\r
993       seqs = selectionGroup.getSequencesInOrder(alignment);\r
994       start = selectionGroup.getStartRes();\r
995       end = selectionGroup.getEndRes()+1;\r
996     }\r
997     else\r
998     {\r
999       iSize = alignment.getHeight();\r
1000       seqs = alignment.getSequencesArray();\r
1001       end = alignment.getWidth();\r
1002     }\r
1003 \r
1004     selection = new String[iSize];\r
1005 \r
1006 \r
1007     for(i=0; i<iSize; i++)\r
1008     {\r
1009       if (hasHiddenColumns)\r
1010       {\r
1011            StringBuffer visibleSeq = new StringBuffer();\r
1012            Vector regions = colSel.getHiddenColumns();\r
1013 \r
1014            int blockStart = start, blockEnd=end;\r
1015            int [] region;\r
1016            int hideStart, hideEnd;\r
1017 \r
1018            for (int j = 0; j < regions.size(); j++)\r
1019            {\r
1020              region = (int[]) regions.elementAt(j);\r
1021              hideStart = region[0];\r
1022              hideEnd = region[1];\r
1023 \r
1024              if(hideStart < start)\r
1025              {\r
1026                continue;\r
1027              }\r
1028 \r
1029              blockStart = Math.min(blockStart, hideEnd+1);\r
1030              blockEnd = Math.min(blockEnd, hideStart);\r
1031 \r
1032              if(blockStart>blockEnd)\r
1033              {\r
1034                 break;\r
1035              }\r
1036 \r
1037 \r
1038              visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));\r
1039 \r
1040              blockStart = hideEnd+1;\r
1041              blockEnd = end;\r
1042            }\r
1043 \r
1044            if(end>blockStart)\r
1045              visibleSeq.append(seqs[i].getSequence(blockStart, end));\r
1046 \r
1047            selection[i] = visibleSeq.toString();\r
1048       }\r
1049       else\r
1050       {\r
1051         selection[i] = seqs[i].getSequence(start, end);\r
1052       }\r
1053     }\r
1054 \r
1055     return selection;\r
1056   }\r
1057 \r
1058   public boolean getShowHiddenMarkers()\r
1059   {\r
1060     return showHiddenMarkers;\r
1061   }\r
1062 \r
1063   public void setShowHiddenMarkers(boolean show)\r
1064   {\r
1065     showHiddenMarkers = show;\r
1066   }\r
1067 \r
1068   public Color getSequenceColour(SequenceI seq)\r
1069   {\r
1070     if (sequenceColours == null || !sequenceColours.containsKey(seq))\r
1071       return Color.white;\r
1072     else\r
1073       return (Color) sequenceColours.get(seq);\r
1074   }\r
1075 \r
1076   public void setSequenceColour(SequenceI seq, Color col)\r
1077   {\r
1078     if (sequenceColours == null)\r
1079       sequenceColours = new Hashtable();\r
1080 \r
1081     if (col == null)\r
1082       sequenceColours.remove(seq);\r
1083     else\r
1084       sequenceColours.put(seq, col);\r
1085   }\r
1086 \r
1087 }\r