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