Invert col sel with hidden cols bug fixed
[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   Stack historyList = new Stack();\r
110   Stack redoList = new Stack();\r
111 \r
112   String sequenceSetID;\r
113 \r
114   public AlignViewport(AlignmentI al, JalviewLite applet)\r
115   {\r
116     this.applet = applet;\r
117     setAlignment(al);\r
118     this.startRes = 0;\r
119     this.endRes = al.getWidth() - 1;\r
120     this.startSeq = 0;\r
121     this.endSeq = al.getHeight() - 1;\r
122     setFont(font);\r
123 \r
124     if(System.getProperty("os.name").startsWith("Mac"))\r
125       MAC = true;\r
126 \r
127     if (applet != null)\r
128     {\r
129       String param = applet.getParameter("showFullId");\r
130       if (param != null)\r
131       {\r
132         showJVSuffix = Boolean.valueOf(param).booleanValue();\r
133       }\r
134 \r
135       param = applet.getParameter("showAnnotation");\r
136       if (param != null)\r
137       {\r
138         showAnnotation = Boolean.valueOf(param).booleanValue();\r
139       }\r
140 \r
141       param = applet.getParameter("showConservation");\r
142       if (param != null)\r
143       {\r
144         showConservation = Boolean.valueOf(param).booleanValue();\r
145       }\r
146 \r
147       param = applet.getParameter("showQuality");\r
148       if (param != null)\r
149       {\r
150         showQuality = Boolean.valueOf(param).booleanValue();\r
151       }\r
152 \r
153       param = applet.getParameter("showConsensus");\r
154       if (param != null)\r
155       {\r
156         showConsensus = Boolean.valueOf(param).booleanValue();\r
157       }\r
158 \r
159       param = applet.getParameter("upperCase");\r
160       if (param != null)\r
161       {\r
162         if(param.equalsIgnoreCase("bold"))\r
163           upperCasebold = true;\r
164       }\r
165 \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       if(hconsensus==null)\r
195       {\r
196         if(!alignment.isNucleotide())\r
197         {\r
198           conservation = new AlignmentAnnotation("Conservation",\r
199               "Conservation of total alignment less than " +\r
200               ConsPercGaps + "% gaps",\r
201               new Annotation[1], 0f,\r
202               11f,\r
203               AlignmentAnnotation.BAR_GRAPH);\r
204           conservation.hasText = true;\r
205 \r
206 \r
207           if (showConservation)\r
208           {\r
209             alignment.addAnnotation(conservation);\r
210           }\r
211 \r
212           if (showQuality)\r
213           {\r
214             quality = new AlignmentAnnotation("Quality",\r
215                                               "Alignment Quality based on Blosum62 scores",\r
216                                               new Annotation[1],\r
217                                               0f,\r
218                                               11f,\r
219                                               AlignmentAnnotation.BAR_GRAPH);\r
220             quality.hasText = true;\r
221 \r
222             alignment.addAnnotation(quality);\r
223           }\r
224         }\r
225 \r
226         consensus = new AlignmentAnnotation("Consensus", "PID",\r
227                                              new Annotation[1], 0f, 100f,\r
228                                              AlignmentAnnotation.BAR_GRAPH);\r
229         consensus.hasText = true;\r
230 \r
231          if (showConsensus)\r
232          {\r
233            alignment.addAnnotation(consensus);\r
234          }\r
235       }\r
236     }\r
237   }\r
238 \r
239   public void showSequenceFeatures(boolean b)\r
240   {\r
241     showSequenceFeatures = b;\r
242   }\r
243 \r
244   public boolean getShowSequenceFeatures()\r
245   {\r
246     return showSequenceFeatures;\r
247   }\r
248 \r
249 \r
250   class ConservationThread extends Thread\r
251   {\r
252     AlignmentPanel ap;\r
253     public ConservationThread(AlignmentPanel ap)\r
254     {\r
255       this.ap = ap;\r
256     }\r
257 \r
258     public void run()\r
259     {\r
260       try\r
261       {\r
262         updatingConservation = true;\r
263 \r
264         while (UPDATING_CONSERVATION)\r
265         {\r
266           try\r
267           {\r
268             if (ap != null)\r
269             {\r
270               ap.repaint();\r
271             }\r
272             Thread.sleep(200);\r
273           }\r
274           catch (Exception ex)\r
275           {\r
276             ex.printStackTrace();\r
277           }\r
278         }\r
279 \r
280         UPDATING_CONSERVATION = true;\r
281 \r
282 \r
283         int alWidth = alignment.getWidth();\r
284         if(alWidth<0)\r
285           return;\r
286 \r
287         Conservation cons = new jalview.analysis.Conservation("All",\r
288             jalview.schemes.ResidueProperties.propHash, 3,\r
289             alignment.getSequences(), 0, alWidth -1);\r
290 \r
291         cons.calculate();\r
292         cons.verdict(false, ConsPercGaps);\r
293 \r
294         if (quality!=null)\r
295         {\r
296           cons.findQuality();\r
297         }\r
298 \r
299         String sequence = cons.getConsSequence().getSequence();\r
300         float minR;\r
301         float minG;\r
302         float minB;\r
303         float maxR;\r
304         float maxG;\r
305         float maxB;\r
306         minR = 0.3f;\r
307         minG = 0.0f;\r
308         minB = 0f;\r
309         maxR = 1.0f - minR;\r
310         maxG = 0.9f - minG;\r
311         maxB = 0f - minB; // scalable range for colouring both Conservation and Quality\r
312 \r
313         float min = 0f;\r
314         float max = 11f;\r
315         float qmin = 0f;\r
316         float qmax = 0f;\r
317 \r
318         char c;\r
319 \r
320         conservation.annotations = new Annotation[alWidth];\r
321 \r
322         if (quality!=null)\r
323         {\r
324           quality.graphMax = cons.qualityRange[1].floatValue();\r
325           quality.annotations = new Annotation[alWidth];\r
326           qmin = cons.qualityRange[0].floatValue();\r
327           qmax = cons.qualityRange[1].floatValue();\r
328         }\r
329 \r
330         for (int i = 0; i < alWidth; i++)\r
331         {\r
332           float value = 0;\r
333 \r
334           c = sequence.charAt(i);\r
335 \r
336           if (Character.isDigit(c))\r
337             value = (int) (c - '0');\r
338           else if (c == '*')\r
339             value = 11;\r
340           else if (c == '+')\r
341             value = 10;\r
342 \r
343           float vprop = value - min;\r
344           vprop /= max;\r
345           conservation.annotations[i] =\r
346               new Annotation(String.valueOf(c),\r
347                              String.valueOf(value), ' ', value,\r
348                              new Color(minR + (maxR * vprop),\r
349                                        minG + (maxG * vprop),\r
350                                        minB + (maxB * vprop)));\r
351 \r
352           // Quality calc\r
353           if (quality!=null)\r
354           {\r
355             value = ( (Double) cons.quality.elementAt(i)).floatValue();\r
356             vprop = value - qmin;\r
357             vprop /= qmax;\r
358             quality.annotations[i] = new Annotation(" ", String.valueOf(value), ' ',\r
359                                              value,\r
360                                              new Color(minR + (maxR * vprop),\r
361                 minG + (maxG * vprop),\r
362                 minB + (maxB * vprop)));\r
363           }\r
364         }\r
365       }\r
366       catch (OutOfMemoryError error)\r
367       {\r
368         System.out.println("Out of memory calculating conservation!!");\r
369         conservation = null;\r
370         quality = null;\r
371         System.gc();\r
372       }\r
373 \r
374       UPDATING_CONSERVATION = false;\r
375       updatingConservation = false;\r
376 \r
377       if(ap!=null)\r
378       {\r
379         ap.repaint();\r
380       }\r
381 \r
382     }\r
383   }\r
384 \r
385 \r
386   ConservationThread conservationThread;\r
387 \r
388   ConsensusThread consensusThread;\r
389 \r
390   boolean consUpdateNeeded = false;\r
391 \r
392   static boolean UPDATING_CONSENSUS = false;\r
393 \r
394   static boolean UPDATING_CONSERVATION = false;\r
395 \r
396   boolean updatingConsensus = false;\r
397 \r
398   boolean updatingConservation = false;\r
399 \r
400   /**\r
401    * DOCUMENT ME!\r
402    */\r
403   public void updateConservation(final AlignmentPanel ap)\r
404   {\r
405     if (alignment.isNucleotide() || conservation==null)\r
406       return;\r
407 \r
408     conservationThread = new ConservationThread(ap);\r
409     conservationThread.start();\r
410   }\r
411 \r
412   /**\r
413    * DOCUMENT ME!\r
414    */\r
415   public void updateConsensus(final AlignmentPanel ap)\r
416   {\r
417     consensusThread = new ConsensusThread(ap);\r
418     consensusThread.start();\r
419   }\r
420 \r
421 \r
422   class ConsensusThread extends Thread\r
423   {\r
424     AlignmentPanel ap;\r
425     public ConsensusThread(AlignmentPanel ap)\r
426     {\r
427       this.ap = ap;\r
428     }\r
429     public void run()\r
430     {\r
431       updatingConsensus = true;\r
432       while (UPDATING_CONSENSUS)\r
433       {\r
434         try\r
435         {\r
436           if (ap != null)\r
437           {\r
438             ap.repaint();\r
439           }\r
440 \r
441           Thread.sleep(200);\r
442         }\r
443         catch (Exception ex)\r
444         {\r
445           ex.printStackTrace();\r
446         }\r
447       }\r
448 \r
449 \r
450       UPDATING_CONSENSUS = true;\r
451 \r
452       try\r
453       {\r
454         int aWidth = alignment.getWidth();\r
455         if(aWidth<0)\r
456           return;\r
457 \r
458         consensus.annotations = null;\r
459         consensus.annotations = new Annotation[aWidth];\r
460 \r
461 \r
462         hconsensus = new Hashtable[aWidth];\r
463         AAFrequency.calculate(alignment.getSequencesArray(),\r
464                               0,\r
465                               alignment.getWidth(),\r
466                               hconsensus);\r
467 \r
468         for (int i = 0; i < aWidth; i++)\r
469         {\r
470           float value = 0;\r
471           if (ignoreGapsInConsensusCalculation)\r
472             value = ( (Float) hconsensus[i].get(AAFrequency.PID_NOGAPS)).\r
473                 floatValue();\r
474           else\r
475             value = ( (Float) hconsensus[i].get(AAFrequency.PID_GAPS)).\r
476                 floatValue();\r
477 \r
478           String maxRes = hconsensus[i].get(AAFrequency.MAXRESIDUE).toString();\r
479           String mouseOver = hconsensus[i].get(AAFrequency.MAXRESIDUE) + " ";\r
480 \r
481           if (maxRes.length() > 1)\r
482           {\r
483             mouseOver = "[" + maxRes + "] ";\r
484             maxRes = "+";\r
485           }\r
486 \r
487           mouseOver += ( (int) value + "%");\r
488           consensus.annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);\r
489         }\r
490 \r
491 \r
492         if (globalColourScheme != null)\r
493           globalColourScheme.setConsensus(hconsensus);\r
494 \r
495       }\r
496       catch (OutOfMemoryError error)\r
497       {\r
498         alignment.deleteAnnotation(consensus);\r
499 \r
500         consensus = null;\r
501         hconsensus = null;\r
502         System.out.println("Out of memory calculating consensus!!");\r
503         System.gc();\r
504       }\r
505       UPDATING_CONSENSUS = false;\r
506       updatingConsensus = false;\r
507 \r
508       if (ap != null)\r
509       {\r
510         ap.repaint();\r
511       }\r
512     }\r
513   }\r
514 \r
515   /**\r
516    * get the consensus sequence as displayed under the PID consensus annotation row.\r
517    * @return consensus sequence as a new sequence object\r
518    */\r
519   /**\r
520    * get the consensus sequence as displayed under the PID consensus annotation row.\r
521    * @return consensus sequence as a new sequence object\r
522    */\r
523   public SequenceI getConsensusSeq()\r
524   {\r
525     if (consensus==null)\r
526       return null;\r
527     StringBuffer seqs=new StringBuffer();\r
528     for (int i=0; i<consensus.annotations.length; i++) {\r
529       if (consensus.annotations[i]!=null) {\r
530         if (consensus.annotations[i].description.charAt(0) == '[')\r
531           seqs.append(consensus.annotations[i].description.charAt(1));\r
532         else\r
533           seqs.append(consensus.annotations[i].displayCharacter);\r
534       }\r
535     }\r
536     SequenceI sq = new Sequence("Consensus", seqs.toString());\r
537     sq.setDescription("Percentage Identity Consensus "+((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));\r
538     return sq;\r
539   }\r
540   public SequenceGroup getSelectionGroup()\r
541   {\r
542     return selectionGroup;\r
543   }\r
544 \r
545   public void setSelectionGroup(SequenceGroup sg)\r
546   {\r
547     selectionGroup = sg;\r
548   }\r
549 \r
550   public boolean getConservationSelected()\r
551   {\r
552     return conservationColourSelected;\r
553   }\r
554 \r
555   public void setConservationSelected(boolean b)\r
556   {\r
557     conservationColourSelected = b;\r
558   }\r
559 \r
560   public boolean getAbovePIDThreshold()\r
561   {\r
562     return abovePIDThreshold;\r
563   }\r
564 \r
565   public void setAbovePIDThreshold(boolean b)\r
566   {\r
567     abovePIDThreshold = b;\r
568   }\r
569 \r
570   public int getStartRes()\r
571   {\r
572     return startRes;\r
573   }\r
574 \r
575   public int getEndRes()\r
576   {\r
577     return endRes;\r
578   }\r
579 \r
580   public int getStartSeq()\r
581   {\r
582     return startSeq;\r
583   }\r
584 \r
585   public void setGlobalColourScheme(ColourSchemeI cs)\r
586   {\r
587     globalColourScheme = cs;\r
588   }\r
589 \r
590   public ColourSchemeI getGlobalColourScheme()\r
591   {\r
592     return globalColourScheme;\r
593   }\r
594 \r
595   public void setStartRes(int res)\r
596   {\r
597     this.startRes = res;\r
598   }\r
599 \r
600   public void setStartSeq(int seq)\r
601   {\r
602     this.startSeq = seq;\r
603   }\r
604 \r
605   public void setEndRes(int res)\r
606   {\r
607     if (res > alignment.getWidth() - 1)\r
608     {\r
609       // log.System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));\r
610       res = alignment.getWidth() - 1;\r
611     }\r
612     if (res < 0)\r
613     {\r
614       res = 0;\r
615     }\r
616     this.endRes = res;\r
617   }\r
618 \r
619   public void setEndSeq(int seq)\r
620   {\r
621     if (seq > alignment.getHeight())\r
622     {\r
623       seq = alignment.getHeight();\r
624     }\r
625     if (seq < 0)\r
626     {\r
627       seq = 0;\r
628     }\r
629     this.endSeq = seq;\r
630   }\r
631 \r
632   public int getEndSeq()\r
633   {\r
634     return endSeq;\r
635   }\r
636 \r
637   java.awt.Frame nullFrame;\r
638   public void setFont(Font f)\r
639   {\r
640     font = f;\r
641     if(nullFrame == null)\r
642     {\r
643       nullFrame = new java.awt.Frame();\r
644       nullFrame.addNotify();\r
645     }\r
646 \r
647     java.awt.FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);\r
648     setCharHeight(fm.getHeight());\r
649     charWidth = fm.charWidth('M');\r
650 \r
651     if(upperCasebold)\r
652     {\r
653       Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());\r
654       fm = nullFrame.getGraphics().getFontMetrics(f2);\r
655       charWidth = fm.stringWidth("MMMMMMMMMMM") / 10;\r
656     }\r
657   }\r
658 \r
659   public Font getFont()\r
660   {\r
661     return font;\r
662   }\r
663 \r
664   public int getCharWidth()\r
665   {\r
666     return charWidth;\r
667   }\r
668 \r
669   public void setCharHeight(int h)\r
670   {\r
671     this.charHeight = h;\r
672   }\r
673 \r
674   public int getCharHeight()\r
675   {\r
676     return charHeight;\r
677   }\r
678 \r
679   public void setWrappedWidth(int w)\r
680   {\r
681     this.wrappedWidth = w;\r
682   }\r
683 \r
684   public int getwrappedWidth()\r
685   {\r
686     return wrappedWidth;\r
687   }\r
688 \r
689   public AlignmentI getAlignment()\r
690   {\r
691     return alignment;\r
692   }\r
693 \r
694   public void setAlignment(AlignmentI align)\r
695   {\r
696     this.alignment = align;\r
697   }\r
698 \r
699   public void setWrapAlignment(boolean state)\r
700   {\r
701     wrapAlignment = state;\r
702   }\r
703 \r
704   public void setShowText(boolean state)\r
705   {\r
706     showText = state;\r
707   }\r
708 \r
709   public void setRenderGaps(boolean state)\r
710   {\r
711     renderGaps = state;\r
712   }\r
713 \r
714   public boolean getColourText()\r
715   {\r
716     return showColourText;\r
717   }\r
718 \r
719   public void setColourText(boolean state)\r
720   {\r
721     showColourText = state;\r
722   }\r
723 \r
724   public void setShowBoxes(boolean state)\r
725   {\r
726     showBoxes = state;\r
727   }\r
728 \r
729   public boolean getWrapAlignment()\r
730   {\r
731     return wrapAlignment;\r
732   }\r
733 \r
734   public boolean getShowText()\r
735   {\r
736     return showText;\r
737   }\r
738 \r
739   public boolean getShowBoxes()\r
740   {\r
741     return showBoxes;\r
742   }\r
743 \r
744   public char getGapCharacter()\r
745   {\r
746     return getAlignment().getGapCharacter();\r
747   }\r
748 \r
749   public void setGapCharacter(char gap)\r
750   {\r
751     if (getAlignment() != null)\r
752     {\r
753       getAlignment().setGapCharacter(gap);\r
754     }\r
755   }\r
756 \r
757   public void setThreshold(int thresh)\r
758   {\r
759     threshold = thresh;\r
760   }\r
761 \r
762   public int getThreshold()\r
763   {\r
764     return threshold;\r
765   }\r
766 \r
767   public void setIncrement(int inc)\r
768   {\r
769     increment = inc;\r
770   }\r
771 \r
772   public int getIncrement()\r
773   {\r
774     return increment;\r
775   }\r
776 \r
777   public void setHiddenColumns(ColumnSelection colsel)\r
778   {\r
779     this.colSel = colsel;\r
780     if(colSel.getHiddenColumns()!=null)\r
781       hasHiddenColumns = true;\r
782   }\r
783 \r
784   public ColumnSelection getColumnSelection()\r
785   {\r
786     return colSel;\r
787   }\r
788 \r
789   public void resetSeqLimits(int height)\r
790   {\r
791     setEndSeq(height / getCharHeight());\r
792   }\r
793 \r
794   public void setCurrentTree(NJTree tree)\r
795   {\r
796     currentTree = tree;\r
797   }\r
798 \r
799   public NJTree getCurrentTree()\r
800   {\r
801     return currentTree;\r
802   }\r
803 \r
804   public void setColourAppliesToAllGroups(boolean b)\r
805   {\r
806     colourAppliesToAllGroups = b;\r
807   }\r
808 \r
809   public boolean getColourAppliesToAllGroups()\r
810   {\r
811     return colourAppliesToAllGroups;\r
812   }\r
813 \r
814   public boolean getShowJVSuffix()\r
815   {\r
816     return showJVSuffix;\r
817   }\r
818 \r
819   public void setShowJVSuffix(boolean b)\r
820   {\r
821     showJVSuffix = b;\r
822   }\r
823 \r
824   public boolean getShowAnnotation()\r
825   {\r
826     return showAnnotation;\r
827   }\r
828 \r
829   public void setShowAnnotation(boolean b)\r
830   {\r
831     showAnnotation = b;\r
832   }\r
833 \r
834   public boolean getScaleAboveWrapped()\r
835   {\r
836     return scaleAboveWrapped;\r
837   }\r
838 \r
839   public boolean getScaleLeftWrapped()\r
840   {\r
841     return scaleLeftWrapped;\r
842   }\r
843 \r
844   public boolean getScaleRightWrapped()\r
845   {\r
846     return scaleRightWrapped;\r
847   }\r
848 \r
849   public void setScaleAboveWrapped(boolean b)\r
850   {\r
851     scaleAboveWrapped = b;\r
852   }\r
853 \r
854   public void setScaleLeftWrapped(boolean b)\r
855   {\r
856     scaleLeftWrapped = b;\r
857   }\r
858 \r
859   public void setScaleRightWrapped(boolean b)\r
860   {\r
861     scaleRightWrapped = b;\r
862   }\r
863 \r
864   public void setIgnoreGapsConsensus(boolean b)\r
865   {\r
866     ignoreGapsInConsensusCalculation = b;\r
867     updateConsensus(null);\r
868     if (globalColourScheme!=null)\r
869     {\r
870       globalColourScheme.setThreshold(globalColourScheme.getThreshold(),\r
871           ignoreGapsInConsensusCalculation);\r
872 \r
873     }\r
874   }\r
875 \r
876   /**\r
877    * Property change listener for changes in alignment\r
878    *\r
879    * @param listener DOCUMENT ME!\r
880    */\r
881   public void addPropertyChangeListener(\r
882       java.beans.PropertyChangeListener listener)\r
883   {\r
884       changeSupport.addPropertyChangeListener(listener);\r
885   }\r
886 \r
887   /**\r
888    * DOCUMENT ME!\r
889    *\r
890    * @param listener DOCUMENT ME!\r
891    */\r
892   public void removePropertyChangeListener(\r
893       java.beans.PropertyChangeListener listener)\r
894   {\r
895       changeSupport.removePropertyChangeListener(listener);\r
896   }\r
897 \r
898   /**\r
899    * Property change listener for changes in alignment\r
900    *\r
901    * @param prop DOCUMENT ME!\r
902    * @param oldvalue DOCUMENT ME!\r
903    * @param newvalue DOCUMENT ME!\r
904    */\r
905   public void firePropertyChange(String prop, Object oldvalue, Object newvalue)\r
906   {\r
907       changeSupport.firePropertyChange(prop, oldvalue, newvalue);\r
908   }\r
909 \r
910 \r
911 \r
912   public boolean getIgnoreGapsConsensus()\r
913   {\r
914     return ignoreGapsInConsensusCalculation;\r
915   }\r
916   public void hideSelectedColumns()\r
917   {\r
918     if (colSel.size() < 1)\r
919       return;\r
920 \r
921     colSel.hideSelectedColumns();\r
922     setSelectionGroup(null);\r
923 \r
924     hasHiddenColumns = true;\r
925   }\r
926 \r
927   public void invertColumnSelection()\r
928   {\r
929     for (int i = 0; i < alignment.getWidth(); i++)\r
930     {\r
931       if (colSel.contains(i))\r
932         colSel.removeElement(i);\r
933       else\r
934       {\r
935         if (!hasHiddenColumns || colSel.isVisible(i))\r
936         {\r
937           colSel.addElement(i);\r
938         }\r
939       }\r
940     }\r
941   }\r
942 \r
943 \r
944   public void hideColumns(int start, int end)\r
945   {\r
946     if(start==end)\r
947       colSel.hideColumns(start);\r
948     else\r
949       colSel.hideColumns(start, end);\r
950 \r
951     hasHiddenColumns = true;\r
952   }\r
953 \r
954   public void hideAllSelectedSeqs()\r
955   {\r
956     if (selectionGroup == null)\r
957       return;\r
958 \r
959     SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);\r
960 \r
961     hideSequence(seqs);\r
962 \r
963     setSelectionGroup(null);\r
964   }\r
965 \r
966   public void hideSequence(SequenceI [] seq)\r
967   {\r
968     if(seq!=null)\r
969     {\r
970       for (int i = 0; i < seq.length; i++)\r
971         alignment.getHiddenSequences().hideSequence(seq[i]);\r
972 \r
973       hasHiddenRows = true;\r
974       firePropertyChange("alignment", null, alignment.getSequences());\r
975     }\r
976   }\r
977 \r
978   public void showColumn(int col)\r
979   {\r
980     colSel.revealHiddenColumns(col);\r
981     if(colSel.getHiddenColumns()==null)\r
982       hasHiddenColumns = false;\r
983   }\r
984 \r
985   public void showAllHiddenColumns()\r
986   {\r
987     colSel.revealAllHiddenColumns();\r
988     hasHiddenColumns = false;\r
989   }\r
990 \r
991   public void showAllHiddenSeqs()\r
992   {\r
993     if(alignment.getHiddenSequences().getSize()>0)\r
994     {\r
995       if(selectionGroup==null)\r
996       {\r
997         selectionGroup = new SequenceGroup();\r
998         selectionGroup.setEndRes(alignment.getWidth()-1);\r
999       }\r
1000       Vector tmp = alignment.getHiddenSequences().showAll();\r
1001       for(int t=0; t<tmp.size(); t++)\r
1002       {\r
1003         selectionGroup.addSequence(\r
1004             (SequenceI)tmp.elementAt(t), false\r
1005             );\r
1006       }\r
1007       firePropertyChange("alignment", null, alignment.getSequences());\r
1008       hasHiddenRows = false;\r
1009     }\r
1010   }\r
1011 \r
1012   public int adjustForHiddenSeqs(int alignmentIndex)\r
1013   {\r
1014     return alignment.getHiddenSequences().adjustForHiddenSeqs(alignmentIndex);\r
1015   }\r
1016 \r
1017   /**\r
1018    * This method returns the a new SequenceI [] with\r
1019    * the selection sequence and start and end points adjusted\r
1020    * @return String[]\r
1021    */\r
1022   public SequenceI[] getSelectionAsNewSequence()\r
1023   {\r
1024     SequenceI[] sequences;\r
1025 \r
1026     if (selectionGroup == null)\r
1027       sequences = alignment.getSequencesArray();\r
1028     else\r
1029       sequences = selectionGroup.getSelectionAsNewSequences(alignment);\r
1030 \r
1031     return sequences;\r
1032   }\r
1033 \r
1034   /**\r
1035    * This method returns the visible alignment as text, as\r
1036    * seen on the GUI, ie if columns are hidden they will not\r
1037    * be returned in the result.\r
1038    * Use this for calculating trees, PCA, redundancy etc on views\r
1039    * which contain hidden columns.\r
1040    * @return String[]\r
1041    */\r
1042   public jalview.datamodel.CigarArray getViewAsCigars(boolean selectedRegionOnly)\r
1043   {\r
1044     CigarArray selection=null;\r
1045     SequenceI [] seqs= null;\r
1046     int i, iSize;\r
1047     int start = 0, end = 0;\r
1048     if(selectedRegionOnly && selectionGroup!=null)\r
1049     {\r
1050       iSize = selectionGroup.getSize(false);\r
1051       seqs = selectionGroup.getSequencesInOrder(alignment);\r
1052       start = selectionGroup.getStartRes();\r
1053       end = selectionGroup.getEndRes(); // inclusive for start and end in SeqCigar constructor\r
1054     }\r
1055     else\r
1056     {\r
1057       iSize = alignment.getHeight();\r
1058       seqs = alignment.getSequencesArray();\r
1059       end = alignment.getWidth()-1;\r
1060     }\r
1061     SeqCigar[] selseqs = new SeqCigar[iSize];\r
1062     for(i=0; i<iSize; i++)\r
1063     {\r
1064       selseqs[i] = new SeqCigar(seqs[i], start, end);\r
1065     }\r
1066     selection=new CigarArray(selseqs);\r
1067     // now construct the CigarArray operations\r
1068     if (hasHiddenColumns) {\r
1069       Vector regions = colSel.getHiddenColumns();\r
1070       int [] region;\r
1071       int hideStart, hideEnd;\r
1072       int last=start;\r
1073       for (int j = 0; last<end & j < regions.size(); j++)\r
1074       {\r
1075         region = (int[]) regions.elementAt(j);\r
1076         hideStart = region[0];\r
1077         hideEnd = region[1];\r
1078         // edit hidden regions to selection range\r
1079         if(hideStart<last) {\r
1080           if (hideEnd > last)\r
1081           {\r
1082             hideStart = last;\r
1083           } else\r
1084             continue;\r
1085         }\r
1086 \r
1087         if (hideStart>end)\r
1088           break;\r
1089 \r
1090         if (hideEnd>end)\r
1091           hideEnd=end;\r
1092 \r
1093         if (hideStart>hideEnd)\r
1094           break;\r
1095         /**\r
1096          * form operations...\r
1097          */\r
1098         if (last<hideStart)\r
1099           selection.addOperation(CigarArray.M, hideStart-last);\r
1100         selection.addOperation(CigarArray.D, 1+hideEnd-hideStart);\r
1101         last = hideEnd+1;\r
1102       }\r
1103       // Final match if necessary.\r
1104       if (last<end)\r
1105         selection.addOperation(CigarArray.M, end-last+1);\r
1106     } else {\r
1107       selection.addOperation(CigarArray.M, end-start+1);\r
1108     }\r
1109     return selection;\r
1110   }\r
1111   /**\r
1112    * return a compact representation of the current alignment selection to\r
1113    * pass to an analysis function\r
1114    * @param selectedOnly boolean true to just return the selected view\r
1115    * @return AlignmentView\r
1116    */\r
1117   jalview.datamodel.AlignmentView getAlignmentView(boolean selectedOnly) {\r
1118     // JBPNote:\r
1119     // this is here because the AlignmentView constructor modifies the CigarArray\r
1120     // object. Refactoring of Cigar and alignment view representation should\r
1121     // be done to remove redundancy.\r
1122     CigarArray aligview = getViewAsCigars(selectedOnly);\r
1123     if (aligview!=null) {\r
1124       return new AlignmentView(aligview,\r
1125           (selectedOnly && selectionGroup!=null) ? selectionGroup.getStartRes() : 0);\r
1126     }\r
1127     return null;\r
1128   }\r
1129   /**\r
1130    * This method returns the visible alignment as text, as\r
1131    * seen on the GUI, ie if columns are hidden they will not\r
1132    * be returned in the result.\r
1133    * Use this for calculating trees, PCA, redundancy etc on views\r
1134    * which contain hidden columns.\r
1135    * @return String[]\r
1136    */\r
1137   public String [] getViewAsString(boolean selectedRegionOnly)\r
1138   {\r
1139     String [] selection = null;\r
1140     SequenceI [] seqs= null;\r
1141     int i, iSize;\r
1142     int start = 0, end = 0;\r
1143     if(selectedRegionOnly && selectionGroup!=null)\r
1144     {\r
1145       iSize = selectionGroup.getSize(false);\r
1146       seqs = selectionGroup.getSequencesInOrder(alignment);\r
1147       start = selectionGroup.getStartRes();\r
1148       end = selectionGroup.getEndRes()+1;\r
1149     }\r
1150     else\r
1151     {\r
1152       iSize = alignment.getHeight();\r
1153       seqs = alignment.getSequencesArray();\r
1154       end = alignment.getWidth();\r
1155     }\r
1156 \r
1157     selection = new String[iSize];\r
1158 \r
1159 \r
1160     for(i=0; i<iSize; i++)\r
1161     {\r
1162       if (hasHiddenColumns)\r
1163       {\r
1164            StringBuffer visibleSeq = new StringBuffer();\r
1165            Vector regions = colSel.getHiddenColumns();\r
1166 \r
1167            int blockStart = start, blockEnd=end;\r
1168            int [] region;\r
1169            int hideStart, hideEnd;\r
1170 \r
1171            for (int j = 0; j < regions.size(); j++)\r
1172            {\r
1173              region = (int[]) regions.elementAt(j);\r
1174              hideStart = region[0];\r
1175              hideEnd = region[1];\r
1176 \r
1177              if(hideStart < start)\r
1178              {\r
1179                continue;\r
1180              }\r
1181 \r
1182              blockStart = Math.min(blockStart, hideEnd+1);\r
1183              blockEnd = Math.min(blockEnd, hideStart);\r
1184 \r
1185              if(blockStart>blockEnd)\r
1186              {\r
1187                 break;\r
1188              }\r
1189 \r
1190 \r
1191              visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));\r
1192 \r
1193              blockStart = hideEnd+1;\r
1194              blockEnd = end;\r
1195            }\r
1196 \r
1197            if(end>blockStart)\r
1198              visibleSeq.append(seqs[i].getSequence(blockStart, end));\r
1199 \r
1200            selection[i] = visibleSeq.toString();\r
1201       }\r
1202       else\r
1203       {\r
1204         selection[i] = seqs[i].getSequence(start, end);\r
1205       }\r
1206     }\r
1207 \r
1208     return selection;\r
1209   }\r
1210 \r
1211   public boolean getShowHiddenMarkers()\r
1212   {\r
1213     return showHiddenMarkers;\r
1214   }\r
1215 \r
1216   public void setShowHiddenMarkers(boolean show)\r
1217   {\r
1218     showHiddenMarkers = show;\r
1219   }\r
1220 \r
1221   public Color getSequenceColour(SequenceI seq)\r
1222   {\r
1223     if (sequenceColours == null || !sequenceColours.containsKey(seq))\r
1224       return Color.white;\r
1225     else\r
1226       return (Color) sequenceColours.get(seq);\r
1227   }\r
1228 \r
1229   public void setSequenceColour(SequenceI seq, Color col)\r
1230   {\r
1231     if (sequenceColours == null)\r
1232       sequenceColours = new Hashtable();\r
1233 \r
1234     if (col == null)\r
1235       sequenceColours.remove(seq);\r
1236     else\r
1237       sequenceColours.put(seq, col);\r
1238   }\r
1239 \r
1240   public String getSequenceSetId()\r
1241   {\r
1242     if (sequenceSetID == null)\r
1243       sequenceSetID = alignment.hashCode() + "";\r
1244 \r
1245     return sequenceSetID;\r
1246   }\r
1247 \r
1248   public void alignmentChanged(AlignmentPanel ap)\r
1249   {\r
1250     alignment.padGaps();\r
1251 \r
1252     if (hconsensus != null && autocalculateConsensus)\r
1253     {\r
1254       updateConsensus(ap);\r
1255       updateConservation(ap);\r
1256     }\r
1257 \r
1258     //Reset endRes of groups if beyond alignment width\r
1259     int alWidth = alignment.getWidth();\r
1260     Vector groups = alignment.getGroups();\r
1261     if(groups!=null)\r
1262     {\r
1263       for(int i=0; i<groups.size(); i++)\r
1264       {\r
1265         SequenceGroup sg = (SequenceGroup)groups.elementAt(i);\r
1266         if(sg.getEndRes()>alWidth)\r
1267           sg.setEndRes(alWidth-1);\r
1268       }\r
1269     }\r
1270 \r
1271     if(selectionGroup!=null && selectionGroup.getEndRes()>alWidth)\r
1272       selectionGroup.setEndRes(alWidth-1);\r
1273 \r
1274     resetAllColourSchemes();\r
1275 \r
1276     alignment.adjustSequenceAnnotations();\r
1277   }\r
1278 \r
1279   void resetAllColourSchemes()\r
1280   {\r
1281     ColourSchemeI cs = globalColourScheme;\r
1282     if(cs!=null)\r
1283     {\r
1284       if (cs instanceof ClustalxColourScheme)\r
1285       {\r
1286         ( (ClustalxColourScheme) cs).\r
1287             resetClustalX(alignment.getSequences(),\r
1288                           alignment.getWidth());\r
1289       }\r
1290 \r
1291       cs.setConsensus(hconsensus);\r
1292       if (cs.conservationApplied())\r
1293       {\r
1294         Alignment al = (Alignment) alignment;\r
1295         Conservation c = new Conservation("All",\r
1296                                           ResidueProperties.propHash, 3,\r
1297                                           al.getSequences(), 0,\r
1298                                           al.getWidth() - 1);\r
1299         c.calculate();\r
1300         c.verdict(false, ConsPercGaps);\r
1301 \r
1302         cs.setConservation(c);\r
1303       }\r
1304     }\r
1305 \r
1306     int s, sSize = alignment.getGroups().size();\r
1307     for(s=0; s<sSize; s++)\r
1308     {\r
1309       SequenceGroup sg = (SequenceGroup)alignment.getGroups().elementAt(s);\r
1310       if(sg.cs!=null && sg.cs instanceof ClustalxColourScheme)\r
1311       {\r
1312         ((ClustalxColourScheme)sg.cs).resetClustalX(\r
1313             sg.getSequences(true), sg.getWidth());\r
1314       }\r
1315       sg.recalcConservation();\r
1316     }\r
1317   }\r
1318 \r
1319 \r
1320 }\r