9a7df7ffc93bf2630d77f8d06f672f20c5672f2f
[jalview.git] / src / jalview / gui / AlignViewport.java
1  /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2006 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.gui;
20
21 import jalview.analysis.*;
22
23 import jalview.bin.*;
24
25 import jalview.datamodel.*;
26
27 import jalview.schemes.*;
28
29 import java.awt.*;
30
31 import java.util.*;
32
33
34 /**
35  * DOCUMENT ME!
36  *
37  * @author $author$
38  * @version $Revision$
39  */
40 public class AlignViewport
41 {
42     int startRes;
43     int endRes;
44     int startSeq;
45     int endSeq;
46     boolean showJVSuffix = true;
47     boolean showText = true;
48     boolean showColourText = false;
49     boolean showBoxes = true;
50     boolean wrapAlignment = false;
51     boolean renderGaps = true;
52     boolean showSequenceFeatures = false;
53     boolean showAnnotation = true;
54     boolean showConservation = true;
55     boolean showQuality = true;
56     boolean showIdentity = true;
57     boolean colourAppliesToAllGroups = true;
58     ColourSchemeI globalColourScheme = null;
59     boolean conservationColourSelected = false;
60     boolean abovePIDThreshold = false;
61     SequenceGroup selectionGroup;
62     int charHeight;
63     int charWidth;
64     boolean validCharWidth;
65     int wrappedWidth;
66     Font font;
67     AlignmentI alignment;
68     ColumnSelection colSel = new ColumnSelection();
69     int threshold;
70     int increment;
71     NJTree currentTree = null;
72     boolean scaleAboveWrapped = false;
73     boolean scaleLeftWrapped = true;
74     boolean scaleRightWrapped = true;
75     boolean hasHiddenColumns = false;
76     boolean hasHiddenRows = false;
77     boolean showHiddenMarkers = true;
78
79     boolean cursorMode = false;
80
81     // The following vector holds the features which are
82     // currently visible, in the correct order or rendering
83     Hashtable featuresDisplayed = null;
84
85
86     /** DOCUMENT ME!! */
87     public Hashtable [] hconsensus;
88     AlignmentAnnotation consensus;
89     AlignmentAnnotation conservation;
90     AlignmentAnnotation quality;
91     boolean autoCalculateConsensus = true;
92
93     /** DOCUMENT ME!! */
94     public int ConsPercGaps = 25; // JBPNote : This should be a scalable property!
95
96     // JBPNote Prolly only need this in the applet version.
97     private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(this);
98
99     boolean ignoreGapsInConsensusCalculation = false;
100
101     boolean isDataset = false;
102
103     boolean antiAlias = false;
104
105     boolean padGaps = false;
106
107     Rectangle explodedPosition;
108
109     String viewName;
110
111     String sequenceSetID;
112
113     boolean gatherViewsHere = false;
114
115
116     public AlignViewport(AlignmentI al, boolean dataset)
117     {
118       isDataset = dataset;
119       setAlignment(al);
120       init();
121     }
122     /**
123      * Creates a new AlignViewport object.
124      *
125      * @param al DOCUMENT ME!
126      */
127     public AlignViewport(AlignmentI al)
128     {
129         setAlignment(al);
130         init();
131     }
132     /**
133      * Create a new AlignViewport with hidden regions
134      * @param al AlignmentI
135      * @param hiddenColumns ColumnSelection
136      */
137     public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns) {
138       setAlignment(al);
139       if (hiddenColumns!=null) {
140         this.colSel = hiddenColumns;
141         if (hiddenColumns.getHiddenColumns() != null)
142           hasHiddenColumns = true;
143       }
144       init();
145     }
146
147     void init()
148     {
149         this.startRes = 0;
150         this.endRes = alignment.getWidth() - 1;
151         this.startSeq = 0;
152         this.endSeq = alignment.getHeight() - 1;
153
154       antiAlias = Cache.getDefault("ANTI_ALIAS", false);
155
156       showJVSuffix = Cache.getDefault("SHOW_JVSUFFIX", true);
157       showAnnotation = Cache.getDefault("SHOW_ANNOTATIONS", true);
158       showConservation = Cache.getDefault("SHOW_CONSERVATION", true);
159
160       showQuality = Cache.getDefault("SHOW_QUALITY", true);
161       showIdentity = Cache.getDefault("SHOW_IDENTITY", true);
162
163       autoCalculateConsensus = Cache.getDefault("AUTO_CALC_CONSENSUS", true);
164
165       padGaps = Cache.getDefault("PAD_GAPS", false);
166
167        String fontName = Cache.getDefault("FONT_NAME", "SansSerif");
168        String fontStyle = Cache.getDefault("FONT_STYLE", Font.PLAIN + "") ;
169        String fontSize = Cache.getDefault("FONT_SIZE", "10");
170
171        int style = 0;
172
173        if (fontStyle.equals("bold"))
174        {
175          style = 1;
176        }
177        else if (fontStyle.equals("italic"))
178        {
179          style = 2;
180        }
181
182        setFont(new Font(fontName, style, Integer.parseInt(fontSize)));
183
184
185        alignment.setGapCharacter( Cache.getDefault("GAP_SYMBOL", "-").charAt(0) );
186
187
188         // We must set conservation and consensus before setting colour,
189         // as Blosum and Clustal require this to be done
190         if(hconsensus==null && !isDataset)
191         {
192           if(!alignment.isNucleotide())
193           {
194             conservation = new AlignmentAnnotation("Conservation",
195                 "Conservation of total alignment less than " +
196                 ConsPercGaps + "% gaps",
197                 new Annotation[1], 0f,
198                 11f,
199                 AlignmentAnnotation.BAR_GRAPH);
200             conservation.hasText = true;
201
202             if (showConservation)
203             {
204               alignment.addAnnotation(conservation);
205             }
206
207             if (showQuality)
208             {
209               quality = new AlignmentAnnotation("Quality",
210                                                 "Alignment Quality based on Blosum62 scores",
211                                                 new Annotation[1],
212                                                 0f,
213                                                 11f,
214                                                 AlignmentAnnotation.BAR_GRAPH);
215               quality.hasText = true;
216
217               alignment.addAnnotation(quality);
218             }
219           }
220
221           consensus = new AlignmentAnnotation("Consensus", "PID",
222                                                new Annotation[1], 0f, 100f,
223                                                AlignmentAnnotation.BAR_GRAPH);
224           consensus.hasText = true;
225
226            if (showIdentity)
227            {
228              alignment.addAnnotation(consensus);
229            }
230
231         }
232
233         if (jalview.bin.Cache.getProperty("DEFAULT_COLOUR") != null)
234         {
235           globalColourScheme = ColourSchemeProperty.getColour(alignment,
236               jalview.bin.Cache.getProperty("DEFAULT_COLOUR"));
237
238             if (globalColourScheme instanceof UserColourScheme)
239             {
240                 globalColourScheme = UserDefinedColours.loadDefaultColours();
241                 ((UserColourScheme)globalColourScheme).setThreshold(0, getIgnoreGapsConsensus());
242             }
243
244             if (globalColourScheme != null)
245             {
246                 globalColourScheme.setConsensus(hconsensus);
247             }
248         }
249     }
250
251
252
253     /**
254      * DOCUMENT ME!
255      *
256      * @param b DOCUMENT ME!
257      */
258     public void setShowSequenceFeatures(boolean b)
259     {
260         showSequenceFeatures = b;
261     }
262
263     public boolean getShowSequenceFeatures()
264     {
265       return showSequenceFeatures;
266     }
267
268
269
270     class ConservationThread extends Thread
271     {
272       AlignmentPanel ap;
273       public ConservationThread(AlignmentPanel ap)
274       {
275         this.ap = ap;
276       }
277
278       public void run()
279       {
280         try
281         {
282           int alWidth = alignment.getWidth();
283
284           Conservation cons = new jalview.analysis.Conservation("All",
285               jalview.schemes.ResidueProperties.propHash, 3,
286               alignment.getSequences(), 0, alWidth -1);
287
288           cons.calculate();
289           cons.verdict(false, ConsPercGaps);
290
291           if (quality!=null)
292           {
293             cons.findQuality();
294           }
295
296
297           String sequence = cons.getConsSequence().getSequence();
298           float minR;
299           float minG;
300           float minB;
301           float maxR;
302           float maxG;
303           float maxB;
304           minR = 0.3f;
305           minG = 0.0f;
306           minB = 0f;
307           maxR = 1.0f - minR;
308           maxG = 0.9f - minG;
309           maxB = 0f - minB; // scalable range for colouring both Conservation and Quality
310
311           float min = 0f;
312           float max = 11f;
313           float qmin = 0f;
314           float qmax = 0f;
315
316           char c;
317
318           conservation.annotations = new Annotation[alWidth];
319
320           if (quality!=null)
321           {
322             quality.graphMax = cons.qualityRange[1].floatValue();
323             quality.annotations = new Annotation[alWidth];
324             qmin = cons.qualityRange[0].floatValue();
325             qmax = cons.qualityRange[1].floatValue();
326           }
327
328           for (int i = 0; i < alWidth; i++)
329           {
330             float value = 0;
331
332             c = sequence.charAt(i);
333
334             if (Character.isDigit(c))
335               value = (int) (c - '0');
336             else if (c == '*')
337               value = 11;
338             else if (c == '+')
339               value = 10;
340
341             float vprop = value - min;
342             vprop /= max;
343             conservation.annotations[i] =
344                 new Annotation(String.valueOf(c),
345                                String.valueOf(value), ' ', value,
346                                new Color(minR + (maxR * vprop),
347                                          minG + (maxG * vprop),
348                                          minB + (maxB * vprop)));
349
350             // Quality calc
351             if (quality!=null)
352             {
353               value = ( (Double) cons.quality.get(i)).floatValue();
354               vprop = value - qmin;
355               vprop /= qmax;
356               quality.annotations[i] = new Annotation(" ", String.valueOf(value), ' ',
357                                                value,
358                                                new Color(minR + (maxR * vprop),
359                   minG + (maxG * vprop),
360                   minB + (maxB * vprop)));
361             }
362           }
363         }
364         catch (OutOfMemoryError error)
365         {
366           javax.swing.SwingUtilities.invokeLater(new Runnable()
367           {
368             public void run()
369             {
370               javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
371                   "Out of memory calculating conservation!!"
372                   +
373                   "\nSee help files for increasing Java Virtual Machine memory."
374                   , "Out of memory",
375                   javax.swing.JOptionPane.WARNING_MESSAGE);
376             }
377           });
378
379           System.out.println("Conservation calculation: " + error);
380           System.gc();
381
382         }
383
384         if(ap!=null)
385         {
386           ap.repaint();
387         }
388         updatingConservation = false;
389       }
390     }
391
392
393     ConservationThread conservationThread;
394
395     ConsensusThread consensusThread;
396
397     boolean consUpdateNeeded = false;
398
399     boolean updatingConsensus = false;
400
401     boolean updatingConservation = false;
402
403     /**
404      * DOCUMENT ME!
405      */
406     public void updateConservation(AlignmentPanel ap)
407     {
408       if (alignment.isNucleotide())
409         return;
410
411       updatingConservation = true;
412
413       if (conservationThread == null || !conservationThread.isAlive())
414       {
415         conservationThread = new ConservationThread(ap);
416         conservationThread.start();
417       }
418       else
419       {
420         consUpdateNeeded = true;
421         System.out.println("come back later");
422       }
423     }
424
425     /**
426      * DOCUMENT ME!
427      */
428     public void updateConsensus(AlignmentPanel ap)
429     {
430       updatingConsensus = true;
431
432       if (consensusThread == null || !consensusThread.isAlive())
433       {
434         consensusThread = new ConsensusThread(ap);
435         consensusThread.start();
436       }
437       else
438       {
439         consUpdateNeeded = true;
440         System.out.println("come back later");
441       }
442     }
443
444
445     class ConsensusThread extends Thread
446     {
447       AlignmentPanel ap;
448       public ConsensusThread(AlignmentPanel ap)
449       {
450         this.ap = ap;
451       }
452       public void run()
453       {
454         try
455         {
456           int aWidth = alignment.getWidth();
457
458           consensus.annotations = null;
459           consensus.annotations = new Annotation[aWidth];
460
461
462           hconsensus = new Hashtable[aWidth];
463           AAFrequency.calculate(alignment.getSequencesArray(),
464                                 0,
465                                 alignment.getWidth(),
466                                 hconsensus);
467
468           for (int i = 0; i < aWidth; i++)
469           {
470             float value = 0;
471             if (ignoreGapsInConsensusCalculation)
472               value = ( (Float) hconsensus[i].get(AAFrequency.PID_NOGAPS)).
473                   floatValue();
474             else
475               value = ( (Float) hconsensus[i].get(AAFrequency.PID_GAPS)).
476                   floatValue();
477
478             String maxRes = hconsensus[i].get(AAFrequency.MAXRESIDUE).toString();
479             String mouseOver = hconsensus[i].get(AAFrequency.MAXRESIDUE) + " ";
480
481             if (maxRes.length() > 1)
482             {
483               mouseOver = "[" + maxRes + "] ";
484               maxRes = "+";
485             }
486
487             mouseOver += ( (int) value + "%");
488             consensus.annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);
489           }
490
491
492           if (globalColourScheme != null)
493             globalColourScheme.setConsensus(hconsensus);
494
495         }
496         catch (OutOfMemoryError error)
497         {
498           javax.swing.SwingUtilities.invokeLater(new Runnable()
499           {
500             public void run()
501             {
502               javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
503                   "Out of memory calculating consensus!!"
504                   +
505                   "\nSee help files for increasing Java Virtual Machine memory."
506                   , "Out of memory",
507                   javax.swing.JOptionPane.WARNING_MESSAGE);
508             }
509           });
510
511           System.out.println("Consensus calculation: " + error);
512           System.gc();
513         }
514
515         if (ap != null)
516         {
517           ap.repaint();
518         }
519
520
521         updatingConsensus = false;
522       }
523     }
524     /**
525      * get the consensus sequence as displayed under the PID consensus annotation row.
526      * @return consensus sequence as a new sequence object
527      */
528     public SequenceI getConsensusSeq() {
529       if (consensus==null)
530         updateConsensus(null);
531       if (consensus==null)
532         return null;
533       StringBuffer seqs=new StringBuffer();
534       for (int i=0; i<consensus.annotations.length; i++) {
535         if (consensus.annotations[i]!=null) {
536           if (consensus.annotations[i].description.charAt(0) == '[')
537             seqs.append(consensus.annotations[i].description.charAt(1));
538           else
539             seqs.append(consensus.annotations[i].displayCharacter);
540         }
541       }
542       SequenceI sq = new Sequence("Consensus", seqs.toString());
543       sq.setDescription("Percentage Identity Consensus "+((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
544       return sq;
545     }
546     /**
547      * DOCUMENT ME!
548      *
549      * @return DOCUMENT ME!
550      */
551     public SequenceGroup getSelectionGroup()
552     {
553         return selectionGroup;
554     }
555
556     /**
557      * DOCUMENT ME!
558      *
559      * @param sg DOCUMENT ME!
560      */
561     public void setSelectionGroup(SequenceGroup sg)
562     {
563         selectionGroup = sg;
564     }
565
566     /**
567      * DOCUMENT ME!
568      *
569      * @return DOCUMENT ME!
570      */
571     public boolean getConservationSelected()
572     {
573         return conservationColourSelected;
574     }
575
576     /**
577      * DOCUMENT ME!
578      *
579      * @param b DOCUMENT ME!
580      */
581     public void setConservationSelected(boolean b)
582     {
583         conservationColourSelected = b;
584     }
585
586     /**
587      * DOCUMENT ME!
588      *
589      * @return DOCUMENT ME!
590      */
591     public boolean getAbovePIDThreshold()
592     {
593         return abovePIDThreshold;
594     }
595
596     /**
597      * DOCUMENT ME!
598      *
599      * @param b DOCUMENT ME!
600      */
601     public void setAbovePIDThreshold(boolean b)
602     {
603         abovePIDThreshold = b;
604     }
605
606     /**
607      * DOCUMENT ME!
608      *
609      * @return DOCUMENT ME!
610      */
611     public int getStartRes()
612     {
613         return startRes;
614     }
615
616     /**
617      * DOCUMENT ME!
618      *
619      * @return DOCUMENT ME!
620      */
621     public int getEndRes()
622     {
623         return endRes;
624     }
625
626     /**
627      * DOCUMENT ME!
628      *
629      * @return DOCUMENT ME!
630      */
631     public int getStartSeq()
632     {
633         return startSeq;
634     }
635
636     /**
637      * DOCUMENT ME!
638      *
639      * @param cs DOCUMENT ME!
640      */
641     public void setGlobalColourScheme(ColourSchemeI cs)
642     {
643         globalColourScheme = cs;
644     }
645
646     /**
647      * DOCUMENT ME!
648      *
649      * @return DOCUMENT ME!
650      */
651     public ColourSchemeI getGlobalColourScheme()
652     {
653         return globalColourScheme;
654     }
655
656     /**
657      * DOCUMENT ME!
658      *
659      * @param res DOCUMENT ME!
660      */
661     public void setStartRes(int res)
662     {
663         this.startRes = res;
664     }
665
666     /**
667      * DOCUMENT ME!
668      *
669      * @param seq DOCUMENT ME!
670      */
671     public void setStartSeq(int seq)
672     {
673         this.startSeq = seq;
674     }
675
676     /**
677      * DOCUMENT ME!
678      *
679      * @param res DOCUMENT ME!
680      */
681     public void setEndRes(int res)
682     {
683         if (res > (alignment.getWidth() - 1))
684         {
685             // log.System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));
686             res = alignment.getWidth() - 1;
687         }
688
689         if (res < 0)
690         {
691             res = 0;
692         }
693
694         this.endRes = res;
695     }
696
697     /**
698      * DOCUMENT ME!
699      *
700      * @param seq DOCUMENT ME!
701      */
702     public void setEndSeq(int seq)
703     {
704         if (seq > alignment.getHeight())
705         {
706             seq = alignment.getHeight();
707         }
708
709         if (seq < 0)
710         {
711             seq = 0;
712         }
713
714         this.endSeq = seq;
715     }
716
717     /**
718      * DOCUMENT ME!
719      *
720      * @return DOCUMENT ME!
721      */
722     public int getEndSeq()
723     {
724         return endSeq;
725     }
726
727     /**
728      * DOCUMENT ME!
729      *
730      * @param f DOCUMENT ME!
731      */
732     public void setFont(Font f)
733     {
734         font = f;
735
736         Container c = new Container();
737
738         java.awt.FontMetrics fm = c.getFontMetrics(font);
739         setCharHeight(fm.getHeight());
740         setCharWidth(fm.charWidth('M'));
741         validCharWidth = true;
742     }
743
744     /**
745      * DOCUMENT ME!
746      *
747      * @return DOCUMENT ME!
748      */
749     public Font getFont()
750     {
751         return font;
752     }
753
754     /**
755      * DOCUMENT ME!
756      *
757      * @param w DOCUMENT ME!
758      */
759     public void setCharWidth(int w)
760     {
761         this.charWidth = w;
762     }
763
764     /**
765      * DOCUMENT ME!
766      *
767      * @return DOCUMENT ME!
768      */
769     public int getCharWidth()
770     {
771         return charWidth;
772     }
773
774     /**
775      * DOCUMENT ME!
776      *
777      * @param h DOCUMENT ME!
778      */
779     public void setCharHeight(int h)
780     {
781         this.charHeight = h;
782     }
783
784     /**
785      * DOCUMENT ME!
786      *
787      * @return DOCUMENT ME!
788      */
789     public int getCharHeight()
790     {
791         return charHeight;
792     }
793
794     /**
795      * DOCUMENT ME!
796      *
797      * @param w DOCUMENT ME!
798      */
799     public void setWrappedWidth(int w)
800     {
801         this.wrappedWidth = w;
802     }
803
804     /**
805      * DOCUMENT ME!
806      *
807      * @return DOCUMENT ME!
808      */
809     public int getWrappedWidth()
810     {
811         return wrappedWidth;
812     }
813
814
815     /**
816      * DOCUMENT ME!
817      *
818      * @return DOCUMENT ME!
819      */
820     public AlignmentI getAlignment()
821     {
822         return alignment;
823     }
824
825     /**
826      * DOCUMENT ME!
827      *
828      * @param align DOCUMENT ME!
829      */
830     public void setAlignment(AlignmentI align)
831     {
832         this.alignment = align;
833     }
834
835     /**
836      * DOCUMENT ME!
837      *
838      * @param state DOCUMENT ME!
839      */
840     public void setWrapAlignment(boolean state)
841     {
842         wrapAlignment = state;
843     }
844
845     /**
846      * DOCUMENT ME!
847      *
848      * @param state DOCUMENT ME!
849      */
850     public void setShowText(boolean state)
851     {
852         showText = state;
853     }
854
855     /**
856      * DOCUMENT ME!
857      *
858      * @param state DOCUMENT ME!
859      */
860     public void setRenderGaps(boolean state)
861     {
862         renderGaps = state;
863     }
864
865     /**
866      * DOCUMENT ME!
867      *
868      * @return DOCUMENT ME!
869      */
870     public boolean getColourText()
871     {
872         return showColourText;
873     }
874
875     /**
876      * DOCUMENT ME!
877      *
878      * @param state DOCUMENT ME!
879      */
880     public void setColourText(boolean state)
881     {
882         showColourText = state;
883     }
884
885     /**
886      * DOCUMENT ME!
887      *
888      * @param state DOCUMENT ME!
889      */
890     public void setShowBoxes(boolean state)
891     {
892         showBoxes = state;
893     }
894
895     /**
896      * DOCUMENT ME!
897      *
898      * @return DOCUMENT ME!
899      */
900     public boolean getWrapAlignment()
901     {
902         return wrapAlignment;
903     }
904
905     /**
906      * DOCUMENT ME!
907      *
908      * @return DOCUMENT ME!
909      */
910     public boolean getShowText()
911     {
912         return showText;
913     }
914
915     /**
916      * DOCUMENT ME!
917      *
918      * @return DOCUMENT ME!
919      */
920     public boolean getShowBoxes()
921     {
922         return showBoxes;
923     }
924
925     /**
926      * DOCUMENT ME!
927      *
928      * @return DOCUMENT ME!
929      */
930     public char getGapCharacter()
931     {
932         return getAlignment().getGapCharacter();
933     }
934
935     /**
936      * DOCUMENT ME!
937      *
938      * @param gap DOCUMENT ME!
939      */
940     public void setGapCharacter(char gap)
941     {
942         if (getAlignment() != null)
943         {
944             getAlignment().setGapCharacter(gap);
945         }
946     }
947
948     /**
949      * DOCUMENT ME!
950      *
951      * @param thresh DOCUMENT ME!
952      */
953     public void setThreshold(int thresh)
954     {
955         threshold = thresh;
956     }
957
958     /**
959      * DOCUMENT ME!
960      *
961      * @return DOCUMENT ME!
962      */
963     public int getThreshold()
964     {
965         return threshold;
966     }
967
968     /**
969      * DOCUMENT ME!
970      *
971      * @param inc DOCUMENT ME!
972      */
973     public void setIncrement(int inc)
974     {
975         increment = inc;
976     }
977
978     /**
979      * DOCUMENT ME!
980      *
981      * @return DOCUMENT ME!
982      */
983     public int getIncrement()
984     {
985         return increment;
986     }
987
988
989     /**
990      * DOCUMENT ME!
991      *
992      * @return DOCUMENT ME!
993      */
994     public ColumnSelection getColumnSelection()
995     {
996         return colSel;
997     }
998
999
1000     /**
1001      * DOCUMENT ME!
1002      *
1003      * @param tree DOCUMENT ME!
1004      */
1005     public void setCurrentTree(NJTree tree)
1006     {
1007         currentTree = tree;
1008     }
1009
1010     /**
1011      * DOCUMENT ME!
1012      *
1013      * @return DOCUMENT ME!
1014      */
1015     public NJTree getCurrentTree()
1016     {
1017         return currentTree;
1018     }
1019
1020     /**
1021      * DOCUMENT ME!
1022      *
1023      * @param b DOCUMENT ME!
1024      */
1025     public void setColourAppliesToAllGroups(boolean b)
1026     {
1027         colourAppliesToAllGroups = b;
1028     }
1029
1030     /**
1031      * DOCUMENT ME!
1032      *
1033      * @return DOCUMENT ME!
1034      */
1035     public boolean getColourAppliesToAllGroups()
1036     {
1037         return colourAppliesToAllGroups;
1038     }
1039
1040     /**
1041      * DOCUMENT ME!
1042      *
1043      * @return DOCUMENT ME!
1044      */
1045     public boolean getShowJVSuffix()
1046     {
1047         return showJVSuffix;
1048     }
1049
1050     /**
1051      * DOCUMENT ME!
1052      *
1053      * @param b DOCUMENT ME!
1054      */
1055     public void setShowJVSuffix(boolean b)
1056     {
1057         showJVSuffix = b;
1058     }
1059
1060
1061     /**
1062      * DOCUMENT ME!
1063      *
1064      * @return DOCUMENT ME!
1065      */
1066     public boolean getShowAnnotation()
1067     {
1068         return showAnnotation;
1069     }
1070
1071     /**
1072      * DOCUMENT ME!
1073      *
1074      * @param b DOCUMENT ME!
1075      */
1076     public void setShowAnnotation(boolean b)
1077     {
1078         showAnnotation = b;
1079     }
1080
1081     /**
1082      * DOCUMENT ME!
1083      *
1084      * @return DOCUMENT ME!
1085      */
1086     public boolean getScaleAboveWrapped()
1087     {
1088         return scaleAboveWrapped;
1089     }
1090
1091     /**
1092      * DOCUMENT ME!
1093      *
1094      * @return DOCUMENT ME!
1095      */
1096     public boolean getScaleLeftWrapped()
1097     {
1098         return scaleLeftWrapped;
1099     }
1100
1101     /**
1102      * DOCUMENT ME!
1103      *
1104      * @return DOCUMENT ME!
1105      */
1106     public boolean getScaleRightWrapped()
1107     {
1108         return scaleRightWrapped;
1109     }
1110
1111     /**
1112      * DOCUMENT ME!
1113      *
1114      * @param b DOCUMENT ME!
1115      */
1116     public void setScaleAboveWrapped(boolean b)
1117     {
1118         scaleAboveWrapped = b;
1119     }
1120
1121     /**
1122      * DOCUMENT ME!
1123      *
1124      * @param b DOCUMENT ME!
1125      */
1126     public void setScaleLeftWrapped(boolean b)
1127     {
1128         scaleLeftWrapped = b;
1129     }
1130
1131     /**
1132      * DOCUMENT ME!
1133      *
1134      * @param b DOCUMENT ME!
1135      */
1136     public void setScaleRightWrapped(boolean b)
1137     {
1138         scaleRightWrapped = b;
1139     }
1140
1141     /**
1142      * Property change listener for changes in alignment
1143      *
1144      * @param listener DOCUMENT ME!
1145      */
1146     public void addPropertyChangeListener(
1147         java.beans.PropertyChangeListener listener)
1148     {
1149         changeSupport.addPropertyChangeListener(listener);
1150     }
1151
1152     /**
1153      * DOCUMENT ME!
1154      *
1155      * @param listener DOCUMENT ME!
1156      */
1157     public void removePropertyChangeListener(
1158         java.beans.PropertyChangeListener listener)
1159     {
1160         changeSupport.removePropertyChangeListener(listener);
1161     }
1162
1163     /**
1164      * Property change listener for changes in alignment
1165      *
1166      * @param prop DOCUMENT ME!
1167      * @param oldvalue DOCUMENT ME!
1168      * @param newvalue DOCUMENT ME!
1169      */
1170     public void firePropertyChange(String prop, Object oldvalue, Object newvalue)
1171     {
1172         changeSupport.firePropertyChange(prop, oldvalue, newvalue);
1173     }
1174
1175     public void setIgnoreGapsConsensus(boolean b, AlignmentPanel ap)
1176     {
1177       ignoreGapsInConsensusCalculation = b;
1178       updateConsensus(ap);
1179       if(globalColourScheme!=null)
1180       {
1181         globalColourScheme.setThreshold(globalColourScheme.getThreshold(), ignoreGapsInConsensusCalculation);
1182       }
1183     }
1184
1185     public boolean getIgnoreGapsConsensus()
1186     {
1187      return ignoreGapsInConsensusCalculation;
1188     }
1189
1190     public void setDataset(boolean b)
1191     {
1192       isDataset = b;
1193     }
1194
1195     public boolean isDataset()
1196     {
1197       return isDataset;
1198     }
1199
1200
1201     public void hideSelectedColumns()
1202     {
1203       if (colSel.size() < 1)
1204         return;
1205
1206       colSel.hideSelectedColumns();
1207       setSelectionGroup(null);
1208
1209       hasHiddenColumns = true;
1210     }
1211
1212
1213     public void hideColumns(int start, int end)
1214     {
1215       if(start==end)
1216         colSel.hideColumns(start);
1217       else
1218         colSel.hideColumns(start, end);
1219
1220       hasHiddenColumns = true;
1221     }
1222
1223     public void hideAllSelectedSeqs()
1224     {
1225       if (selectionGroup == null)
1226         return;
1227
1228       SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);
1229
1230       hideSequence(seqs);
1231
1232       setSelectionGroup(null);
1233     }
1234
1235     public void hideSequence(SequenceI [] seq)
1236     {
1237       if(seq!=null)
1238       {
1239         for (int i = 0; i < seq.length; i++)
1240           alignment.getHiddenSequences().hideSequence(seq[i]);
1241
1242         hasHiddenRows = true;
1243         firePropertyChange("alignment", null, alignment.getSequences());
1244       }
1245     }
1246
1247     public void showSequence(int index)
1248     {
1249       Vector tmp = alignment.getHiddenSequences().showSequence(index);
1250       if(tmp.size()>0)
1251       {
1252         if(selectionGroup==null)
1253         {
1254           selectionGroup = new SequenceGroup();
1255           selectionGroup.setEndRes(alignment.getWidth()-1);
1256         }
1257
1258         for (int t = 0; t < tmp.size(); t++)
1259         {
1260           selectionGroup.addSequence(
1261               (SequenceI) tmp.elementAt(t), false
1262               );
1263         }
1264         firePropertyChange("alignment", null, alignment.getSequences());
1265       }
1266
1267       if(alignment.getHiddenSequences().getSize()<1)
1268         hasHiddenRows = false;
1269     }
1270
1271     public void showColumn(int col)
1272     {
1273       colSel.revealHiddenColumns(col);
1274       if(colSel.getHiddenColumns()==null)
1275         hasHiddenColumns = false;
1276     }
1277
1278     public void showAllHiddenColumns()
1279     {
1280       colSel.revealAllHiddenColumns();
1281       hasHiddenColumns = false;
1282     }
1283
1284     public void showAllHiddenSeqs()
1285     {
1286       if(alignment.getHiddenSequences().getSize()>0)
1287       {
1288         if(selectionGroup==null)
1289         {
1290           selectionGroup = new SequenceGroup();
1291           selectionGroup.setEndRes(alignment.getWidth()-1);
1292         }
1293         Vector tmp = alignment.getHiddenSequences().showAll();
1294         for(int t=0; t<tmp.size(); t++)
1295         {
1296           selectionGroup.addSequence(
1297               (SequenceI)tmp.elementAt(t), false
1298               );
1299         }
1300         firePropertyChange("alignment", null, alignment.getSequences());
1301         hasHiddenRows = false;
1302       }
1303     }
1304
1305     public void invertColumnSelection()
1306     {
1307       int column;
1308       for(int i=0; i<alignment.getWidth(); i++)
1309       {
1310         column = i;
1311
1312         if(colSel.contains(column))
1313           colSel.removeElement(column);
1314         else
1315           colSel.addElement(column);
1316
1317       }
1318
1319     }
1320
1321     public int adjustForHiddenSeqs(int alignmentIndex)
1322     {
1323       return alignment.getHiddenSequences().adjustForHiddenSeqs(alignmentIndex);
1324     }
1325
1326     /**
1327      * This method returns the a new SequenceI [] with
1328      * the selection sequence and start and end points adjusted
1329      * @return String[]
1330      */
1331     public SequenceI[] getSelectionAsNewSequence()
1332     {
1333       SequenceI[] sequences;
1334
1335       if (selectionGroup == null)
1336         sequences = alignment.getSequencesArray();
1337       else
1338         sequences = selectionGroup.getSelectionAsNewSequences(alignment);
1339
1340       return sequences;
1341     }
1342
1343     /**
1344      * This method returns the visible alignment as text, as
1345      * seen on the GUI, ie if columns are hidden they will not
1346      * be returned in the result.
1347      * Use this for calculating trees, PCA, redundancy etc on views
1348      * which contain hidden columns.
1349      * @return String[]
1350      */
1351     public jalview.datamodel.CigarArray getViewAsCigars(boolean selectedRegionOnly)
1352     {
1353       CigarArray selection=null;
1354       SequenceI [] seqs= null;
1355       int i, iSize;
1356       int start = 0, end = 0;
1357       if(selectedRegionOnly && selectionGroup!=null)
1358       {
1359         iSize = selectionGroup.getSize(false);
1360         seqs = selectionGroup.getSequencesInOrder(alignment);
1361         start = selectionGroup.getStartRes();
1362         end = selectionGroup.getEndRes(); // inclusive for start and end in SeqCigar constructor
1363       }
1364       else
1365       {
1366         iSize = alignment.getHeight();
1367         seqs = alignment.getSequencesArray();
1368         end = alignment.getWidth()-1;
1369       }
1370       SeqCigar[] selseqs = new SeqCigar[iSize];
1371       for(i=0; i<iSize; i++)
1372       {
1373         selseqs[i] = new SeqCigar(seqs[i], start, end);
1374       }
1375       selection=new CigarArray(selseqs);
1376       // now construct the CigarArray operations
1377       if (hasHiddenColumns) {
1378         Vector regions = colSel.getHiddenColumns();
1379         int [] region;
1380         int hideStart, hideEnd;
1381         int last=start;
1382         for (int j = 0; last<end & j < regions.size(); j++)
1383         {
1384           region = (int[]) regions.elementAt(j);
1385           hideStart = region[0];
1386           hideEnd = region[1];
1387           // edit hidden regions to selection range
1388           if(hideStart<last) {
1389             if (hideEnd > last)
1390             {
1391               hideStart = last;
1392             } else
1393               continue;
1394           }
1395
1396           if (hideStart>end)
1397             break;
1398
1399           if (hideEnd>end)
1400             hideEnd=end;
1401
1402           if (hideStart>hideEnd)
1403             break;
1404           /**
1405            * form operations...
1406            */
1407           if (last<hideStart)
1408             selection.addOperation(CigarArray.M, hideStart-last);
1409           selection.addOperation(CigarArray.D, 1+hideEnd-hideStart);
1410           last = hideEnd+1;
1411         }
1412         // Final match if necessary.
1413         if (last<end)
1414           selection.addOperation(CigarArray.M, end-last+1);
1415       } else {
1416         selection.addOperation(CigarArray.M, end-start+1);
1417       }
1418       return selection;
1419     }
1420     /**
1421      * return a compact representation of the current alignment selection to
1422      * pass to an analysis function
1423      * @param selectedOnly boolean true to just return the selected view
1424      * @return AlignmentView
1425      */
1426     jalview.datamodel.AlignmentView getAlignmentView(boolean selectedOnly) {
1427       // JBPNote:
1428       // this is here because the AlignmentView constructor modifies the CigarArray
1429       // object. Refactoring of Cigar and alignment view representation should
1430       // be done to remove redundancy.
1431       CigarArray aligview = getViewAsCigars(selectedOnly);
1432       if (aligview!=null) {
1433         return new AlignmentView(aligview,
1434             (selectedOnly && selectionGroup!=null) ? selectionGroup.getStartRes() : 0);
1435       }
1436       return null;
1437     }
1438     /**
1439      * This method returns the visible alignment as text, as
1440      * seen on the GUI, ie if columns are hidden they will not
1441      * be returned in the result.
1442      * Use this for calculating trees, PCA, redundancy etc on views
1443      * which contain hidden columns.
1444      * @return String[]
1445      */
1446     public String [] getViewAsString(boolean selectedRegionOnly)
1447     {
1448       String [] selection = null;
1449       SequenceI [] seqs= null;
1450       int i, iSize;
1451       int start = 0, end = 0;
1452       if(selectedRegionOnly && selectionGroup!=null)
1453       {
1454         iSize = selectionGroup.getSize(false);
1455         seqs = selectionGroup.getSequencesInOrder(alignment);
1456         start = selectionGroup.getStartRes();
1457         end = selectionGroup.getEndRes()+1;
1458       }
1459       else
1460       {
1461         iSize = alignment.getHeight();
1462         seqs = alignment.getSequencesArray();
1463         end = alignment.getWidth();
1464       }
1465
1466       selection = new String[iSize];
1467       if (hasHiddenColumns) {
1468         selection = colSel.getVisibleSequenceStrings(start, end, seqs);
1469       } else {
1470         for(i=0; i<iSize; i++)
1471         {
1472           selection[i] = seqs[i].getSequence(start, end);
1473         }
1474
1475       }
1476       return selection;
1477     }
1478
1479     public boolean getShowHiddenMarkers()
1480     {
1481       return showHiddenMarkers;
1482     }
1483
1484     public void setShowHiddenMarkers(boolean show)
1485     {
1486       showHiddenMarkers = show;
1487     }
1488
1489     public String getSequenceSetId()
1490     {
1491       if(sequenceSetID==null)
1492         sequenceSetID =  alignment.hashCode()+"";
1493
1494       return sequenceSetID;
1495     }
1496
1497 }