fb3d4df9946ff566d17bb2794b486b322c16dc39
[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
369
370             public void run()
371             {
372               javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
373                   "Out of memory calculating conservation!!"
374                   +
375                   "\nSee help files for increasing Java Virtual Machine memory."
376                   , "Out of memory",
377                   javax.swing.JOptionPane.WARNING_MESSAGE);
378             }
379           });
380
381           conservation = null;
382           quality = null;
383
384           System.out.println("Conservation calculation: " + error);
385           System.gc();
386
387         }
388
389         if(ap!=null)
390         {
391           ap.repaint();
392         }
393         updatingConservation = false;
394       }
395     }
396
397
398     ConservationThread conservationThread;
399
400     ConsensusThread consensusThread;
401
402     boolean consUpdateNeeded = false;
403
404     boolean updatingConsensus = false;
405
406     boolean updatingConservation = false;
407
408     /**
409      * DOCUMENT ME!
410      */
411     public void updateConservation(AlignmentPanel ap)
412     {
413       if (alignment.isNucleotide())
414         return;
415
416       updatingConservation = true;
417
418       if (conservationThread == null || !conservationThread.isAlive())
419       {
420         conservationThread = new ConservationThread(ap);
421         conservationThread.start();
422       }
423       else
424       {
425         consUpdateNeeded = true;
426         System.out.println("come back later");
427       }
428     }
429
430     /**
431      * DOCUMENT ME!
432      */
433     public void updateConsensus(AlignmentPanel ap)
434     {
435       updatingConsensus = true;
436
437       if (consensusThread == null || !consensusThread.isAlive())
438       {
439         consensusThread = new ConsensusThread(ap);
440         consensusThread.start();
441       }
442       else
443       {
444         consUpdateNeeded = true;
445         System.out.println("come back later");
446       }
447     }
448
449
450     class ConsensusThread extends Thread
451     {
452       AlignmentPanel ap;
453       public ConsensusThread(AlignmentPanel ap)
454       {
455         this.ap = ap;
456       }
457       public void run()
458       {
459         try
460         {
461           int aWidth = alignment.getWidth();
462
463           consensus.annotations = null;
464           consensus.annotations = new Annotation[aWidth];
465
466
467           hconsensus = new Hashtable[aWidth];
468           AAFrequency.calculate(alignment.getSequencesArray(),
469                                 0,
470                                 alignment.getWidth(),
471                                 hconsensus);
472
473           for (int i = 0; i < aWidth; i++)
474           {
475             float value = 0;
476             if (ignoreGapsInConsensusCalculation)
477               value = ( (Float) hconsensus[i].get(AAFrequency.PID_NOGAPS)).
478                   floatValue();
479             else
480               value = ( (Float) hconsensus[i].get(AAFrequency.PID_GAPS)).
481                   floatValue();
482
483             String maxRes = hconsensus[i].get(AAFrequency.MAXRESIDUE).toString();
484             String mouseOver = hconsensus[i].get(AAFrequency.MAXRESIDUE) + " ";
485
486             if (maxRes.length() > 1)
487             {
488               mouseOver = "[" + maxRes + "] ";
489               maxRes = "+";
490             }
491
492             mouseOver += ( (int) value + "%");
493             consensus.annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);
494           }
495
496
497           if (globalColourScheme != null)
498             globalColourScheme.setConsensus(hconsensus);
499
500         }
501         catch (OutOfMemoryError error)
502         {
503           javax.swing.SwingUtilities.invokeLater(new Runnable()
504           {
505             public void run()
506             {
507               javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
508                   "Out of memory calculating consensus!!"
509                   +
510                   "\nSee help files for increasing Java Virtual Machine memory."
511                   , "Out of memory",
512                   javax.swing.JOptionPane.WARNING_MESSAGE);
513             }
514           });
515
516           System.out.println("Consensus calculation: " + error);
517           System.gc();
518         }
519
520         if (ap != null)
521         {
522           ap.repaint();
523         }
524
525
526         updatingConsensus = false;
527       }
528     }
529     /**
530      * get the consensus sequence as displayed under the PID consensus annotation row.
531      * @return consensus sequence as a new sequence object
532      */
533     public SequenceI getConsensusSeq() {
534       if (consensus==null)
535         updateConsensus(null);
536       if (consensus==null)
537         return null;
538       StringBuffer seqs=new StringBuffer();
539       for (int i=0; i<consensus.annotations.length; i++) {
540         if (consensus.annotations[i]!=null) {
541           if (consensus.annotations[i].description.charAt(0) == '[')
542             seqs.append(consensus.annotations[i].description.charAt(1));
543           else
544             seqs.append(consensus.annotations[i].displayCharacter);
545         }
546       }
547       SequenceI sq = new Sequence("Consensus", seqs.toString());
548       sq.setDescription("Percentage Identity Consensus "+((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
549       return sq;
550     }
551     /**
552      * DOCUMENT ME!
553      *
554      * @return DOCUMENT ME!
555      */
556     public SequenceGroup getSelectionGroup()
557     {
558         return selectionGroup;
559     }
560
561     /**
562      * DOCUMENT ME!
563      *
564      * @param sg DOCUMENT ME!
565      */
566     public void setSelectionGroup(SequenceGroup sg)
567     {
568         selectionGroup = sg;
569     }
570
571     /**
572      * DOCUMENT ME!
573      *
574      * @return DOCUMENT ME!
575      */
576     public boolean getConservationSelected()
577     {
578         return conservationColourSelected;
579     }
580
581     /**
582      * DOCUMENT ME!
583      *
584      * @param b DOCUMENT ME!
585      */
586     public void setConservationSelected(boolean b)
587     {
588         conservationColourSelected = b;
589     }
590
591     /**
592      * DOCUMENT ME!
593      *
594      * @return DOCUMENT ME!
595      */
596     public boolean getAbovePIDThreshold()
597     {
598         return abovePIDThreshold;
599     }
600
601     /**
602      * DOCUMENT ME!
603      *
604      * @param b DOCUMENT ME!
605      */
606     public void setAbovePIDThreshold(boolean b)
607     {
608         abovePIDThreshold = b;
609     }
610
611     /**
612      * DOCUMENT ME!
613      *
614      * @return DOCUMENT ME!
615      */
616     public int getStartRes()
617     {
618         return startRes;
619     }
620
621     /**
622      * DOCUMENT ME!
623      *
624      * @return DOCUMENT ME!
625      */
626     public int getEndRes()
627     {
628         return endRes;
629     }
630
631     /**
632      * DOCUMENT ME!
633      *
634      * @return DOCUMENT ME!
635      */
636     public int getStartSeq()
637     {
638         return startSeq;
639     }
640
641     /**
642      * DOCUMENT ME!
643      *
644      * @param cs DOCUMENT ME!
645      */
646     public void setGlobalColourScheme(ColourSchemeI cs)
647     {
648         globalColourScheme = cs;
649     }
650
651     /**
652      * DOCUMENT ME!
653      *
654      * @return DOCUMENT ME!
655      */
656     public ColourSchemeI getGlobalColourScheme()
657     {
658         return globalColourScheme;
659     }
660
661     /**
662      * DOCUMENT ME!
663      *
664      * @param res DOCUMENT ME!
665      */
666     public void setStartRes(int res)
667     {
668         this.startRes = res;
669     }
670
671     /**
672      * DOCUMENT ME!
673      *
674      * @param seq DOCUMENT ME!
675      */
676     public void setStartSeq(int seq)
677     {
678         this.startSeq = seq;
679     }
680
681     /**
682      * DOCUMENT ME!
683      *
684      * @param res DOCUMENT ME!
685      */
686     public void setEndRes(int res)
687     {
688         if (res > (alignment.getWidth() - 1))
689         {
690             // log.System.out.println(" Corrected res from " + res + " to maximum " + (alignment.getWidth()-1));
691             res = alignment.getWidth() - 1;
692         }
693
694         if (res < 0)
695         {
696             res = 0;
697         }
698
699         this.endRes = res;
700     }
701
702     /**
703      * DOCUMENT ME!
704      *
705      * @param seq DOCUMENT ME!
706      */
707     public void setEndSeq(int seq)
708     {
709         if (seq > alignment.getHeight())
710         {
711             seq = alignment.getHeight();
712         }
713
714         if (seq < 0)
715         {
716             seq = 0;
717         }
718
719         this.endSeq = seq;
720     }
721
722     /**
723      * DOCUMENT ME!
724      *
725      * @return DOCUMENT ME!
726      */
727     public int getEndSeq()
728     {
729         return endSeq;
730     }
731
732     /**
733      * DOCUMENT ME!
734      *
735      * @param f DOCUMENT ME!
736      */
737     public void setFont(Font f)
738     {
739         font = f;
740
741         Container c = new Container();
742
743         java.awt.FontMetrics fm = c.getFontMetrics(font);
744         setCharHeight(fm.getHeight());
745         setCharWidth(fm.charWidth('M'));
746         validCharWidth = true;
747     }
748
749     /**
750      * DOCUMENT ME!
751      *
752      * @return DOCUMENT ME!
753      */
754     public Font getFont()
755     {
756         return font;
757     }
758
759     /**
760      * DOCUMENT ME!
761      *
762      * @param w DOCUMENT ME!
763      */
764     public void setCharWidth(int w)
765     {
766         this.charWidth = w;
767     }
768
769     /**
770      * DOCUMENT ME!
771      *
772      * @return DOCUMENT ME!
773      */
774     public int getCharWidth()
775     {
776         return charWidth;
777     }
778
779     /**
780      * DOCUMENT ME!
781      *
782      * @param h DOCUMENT ME!
783      */
784     public void setCharHeight(int h)
785     {
786         this.charHeight = h;
787     }
788
789     /**
790      * DOCUMENT ME!
791      *
792      * @return DOCUMENT ME!
793      */
794     public int getCharHeight()
795     {
796         return charHeight;
797     }
798
799     /**
800      * DOCUMENT ME!
801      *
802      * @param w DOCUMENT ME!
803      */
804     public void setWrappedWidth(int w)
805     {
806         this.wrappedWidth = w;
807     }
808
809     /**
810      * DOCUMENT ME!
811      *
812      * @return DOCUMENT ME!
813      */
814     public int getWrappedWidth()
815     {
816         return wrappedWidth;
817     }
818
819
820     /**
821      * DOCUMENT ME!
822      *
823      * @return DOCUMENT ME!
824      */
825     public AlignmentI getAlignment()
826     {
827         return alignment;
828     }
829
830     /**
831      * DOCUMENT ME!
832      *
833      * @param align DOCUMENT ME!
834      */
835     public void setAlignment(AlignmentI align)
836     {
837         this.alignment = align;
838     }
839
840     /**
841      * DOCUMENT ME!
842      *
843      * @param state DOCUMENT ME!
844      */
845     public void setWrapAlignment(boolean state)
846     {
847         wrapAlignment = state;
848     }
849
850     /**
851      * DOCUMENT ME!
852      *
853      * @param state DOCUMENT ME!
854      */
855     public void setShowText(boolean state)
856     {
857         showText = state;
858     }
859
860     /**
861      * DOCUMENT ME!
862      *
863      * @param state DOCUMENT ME!
864      */
865     public void setRenderGaps(boolean state)
866     {
867         renderGaps = state;
868     }
869
870     /**
871      * DOCUMENT ME!
872      *
873      * @return DOCUMENT ME!
874      */
875     public boolean getColourText()
876     {
877         return showColourText;
878     }
879
880     /**
881      * DOCUMENT ME!
882      *
883      * @param state DOCUMENT ME!
884      */
885     public void setColourText(boolean state)
886     {
887         showColourText = state;
888     }
889
890     /**
891      * DOCUMENT ME!
892      *
893      * @param state DOCUMENT ME!
894      */
895     public void setShowBoxes(boolean state)
896     {
897         showBoxes = state;
898     }
899
900     /**
901      * DOCUMENT ME!
902      *
903      * @return DOCUMENT ME!
904      */
905     public boolean getWrapAlignment()
906     {
907         return wrapAlignment;
908     }
909
910     /**
911      * DOCUMENT ME!
912      *
913      * @return DOCUMENT ME!
914      */
915     public boolean getShowText()
916     {
917         return showText;
918     }
919
920     /**
921      * DOCUMENT ME!
922      *
923      * @return DOCUMENT ME!
924      */
925     public boolean getShowBoxes()
926     {
927         return showBoxes;
928     }
929
930     /**
931      * DOCUMENT ME!
932      *
933      * @return DOCUMENT ME!
934      */
935     public char getGapCharacter()
936     {
937         return getAlignment().getGapCharacter();
938     }
939
940     /**
941      * DOCUMENT ME!
942      *
943      * @param gap DOCUMENT ME!
944      */
945     public void setGapCharacter(char gap)
946     {
947         if (getAlignment() != null)
948         {
949             getAlignment().setGapCharacter(gap);
950         }
951     }
952
953     /**
954      * DOCUMENT ME!
955      *
956      * @param thresh DOCUMENT ME!
957      */
958     public void setThreshold(int thresh)
959     {
960         threshold = thresh;
961     }
962
963     /**
964      * DOCUMENT ME!
965      *
966      * @return DOCUMENT ME!
967      */
968     public int getThreshold()
969     {
970         return threshold;
971     }
972
973     /**
974      * DOCUMENT ME!
975      *
976      * @param inc DOCUMENT ME!
977      */
978     public void setIncrement(int inc)
979     {
980         increment = inc;
981     }
982
983     /**
984      * DOCUMENT ME!
985      *
986      * @return DOCUMENT ME!
987      */
988     public int getIncrement()
989     {
990         return increment;
991     }
992
993
994     /**
995      * DOCUMENT ME!
996      *
997      * @return DOCUMENT ME!
998      */
999     public ColumnSelection getColumnSelection()
1000     {
1001         return colSel;
1002     }
1003
1004
1005     /**
1006      * DOCUMENT ME!
1007      *
1008      * @param tree DOCUMENT ME!
1009      */
1010     public void setCurrentTree(NJTree tree)
1011     {
1012         currentTree = tree;
1013     }
1014
1015     /**
1016      * DOCUMENT ME!
1017      *
1018      * @return DOCUMENT ME!
1019      */
1020     public NJTree getCurrentTree()
1021     {
1022         return currentTree;
1023     }
1024
1025     /**
1026      * DOCUMENT ME!
1027      *
1028      * @param b DOCUMENT ME!
1029      */
1030     public void setColourAppliesToAllGroups(boolean b)
1031     {
1032         colourAppliesToAllGroups = b;
1033     }
1034
1035     /**
1036      * DOCUMENT ME!
1037      *
1038      * @return DOCUMENT ME!
1039      */
1040     public boolean getColourAppliesToAllGroups()
1041     {
1042         return colourAppliesToAllGroups;
1043     }
1044
1045     /**
1046      * DOCUMENT ME!
1047      *
1048      * @return DOCUMENT ME!
1049      */
1050     public boolean getShowJVSuffix()
1051     {
1052         return showJVSuffix;
1053     }
1054
1055     /**
1056      * DOCUMENT ME!
1057      *
1058      * @param b DOCUMENT ME!
1059      */
1060     public void setShowJVSuffix(boolean b)
1061     {
1062         showJVSuffix = b;
1063     }
1064
1065
1066     /**
1067      * DOCUMENT ME!
1068      *
1069      * @return DOCUMENT ME!
1070      */
1071     public boolean getShowAnnotation()
1072     {
1073         return showAnnotation;
1074     }
1075
1076     /**
1077      * DOCUMENT ME!
1078      *
1079      * @param b DOCUMENT ME!
1080      */
1081     public void setShowAnnotation(boolean b)
1082     {
1083         showAnnotation = b;
1084     }
1085
1086     /**
1087      * DOCUMENT ME!
1088      *
1089      * @return DOCUMENT ME!
1090      */
1091     public boolean getScaleAboveWrapped()
1092     {
1093         return scaleAboveWrapped;
1094     }
1095
1096     /**
1097      * DOCUMENT ME!
1098      *
1099      * @return DOCUMENT ME!
1100      */
1101     public boolean getScaleLeftWrapped()
1102     {
1103         return scaleLeftWrapped;
1104     }
1105
1106     /**
1107      * DOCUMENT ME!
1108      *
1109      * @return DOCUMENT ME!
1110      */
1111     public boolean getScaleRightWrapped()
1112     {
1113         return scaleRightWrapped;
1114     }
1115
1116     /**
1117      * DOCUMENT ME!
1118      *
1119      * @param b DOCUMENT ME!
1120      */
1121     public void setScaleAboveWrapped(boolean b)
1122     {
1123         scaleAboveWrapped = b;
1124     }
1125
1126     /**
1127      * DOCUMENT ME!
1128      *
1129      * @param b DOCUMENT ME!
1130      */
1131     public void setScaleLeftWrapped(boolean b)
1132     {
1133         scaleLeftWrapped = b;
1134     }
1135
1136     /**
1137      * DOCUMENT ME!
1138      *
1139      * @param b DOCUMENT ME!
1140      */
1141     public void setScaleRightWrapped(boolean b)
1142     {
1143         scaleRightWrapped = b;
1144     }
1145
1146     /**
1147      * Property change listener for changes in alignment
1148      *
1149      * @param listener DOCUMENT ME!
1150      */
1151     public void addPropertyChangeListener(
1152         java.beans.PropertyChangeListener listener)
1153     {
1154         changeSupport.addPropertyChangeListener(listener);
1155     }
1156
1157     /**
1158      * DOCUMENT ME!
1159      *
1160      * @param listener DOCUMENT ME!
1161      */
1162     public void removePropertyChangeListener(
1163         java.beans.PropertyChangeListener listener)
1164     {
1165         changeSupport.removePropertyChangeListener(listener);
1166     }
1167
1168     /**
1169      * Property change listener for changes in alignment
1170      *
1171      * @param prop DOCUMENT ME!
1172      * @param oldvalue DOCUMENT ME!
1173      * @param newvalue DOCUMENT ME!
1174      */
1175     public void firePropertyChange(String prop, Object oldvalue, Object newvalue)
1176     {
1177         changeSupport.firePropertyChange(prop, oldvalue, newvalue);
1178     }
1179
1180     public void setIgnoreGapsConsensus(boolean b, AlignmentPanel ap)
1181     {
1182       ignoreGapsInConsensusCalculation = b;
1183       updateConsensus(ap);
1184       if(globalColourScheme!=null)
1185       {
1186         globalColourScheme.setThreshold(globalColourScheme.getThreshold(), ignoreGapsInConsensusCalculation);
1187       }
1188     }
1189
1190     public boolean getIgnoreGapsConsensus()
1191     {
1192      return ignoreGapsInConsensusCalculation;
1193     }
1194
1195     public void setDataset(boolean b)
1196     {
1197       isDataset = b;
1198     }
1199
1200     public boolean isDataset()
1201     {
1202       return isDataset;
1203     }
1204
1205
1206     public void hideSelectedColumns()
1207     {
1208       if (colSel.size() < 1)
1209         return;
1210
1211       colSel.hideSelectedColumns();
1212       setSelectionGroup(null);
1213
1214       hasHiddenColumns = true;
1215     }
1216
1217
1218     public void hideColumns(int start, int end)
1219     {
1220       if(start==end)
1221         colSel.hideColumns(start);
1222       else
1223         colSel.hideColumns(start, end);
1224
1225       hasHiddenColumns = true;
1226     }
1227
1228     public void hideAllSelectedSeqs()
1229     {
1230       if (selectionGroup == null)
1231         return;
1232
1233       SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);
1234
1235       hideSequence(seqs);
1236
1237       setSelectionGroup(null);
1238     }
1239
1240     public void hideSequence(SequenceI [] seq)
1241     {
1242       if(seq!=null)
1243       {
1244         for (int i = 0; i < seq.length; i++)
1245           alignment.getHiddenSequences().hideSequence(seq[i]);
1246
1247         hasHiddenRows = true;
1248         firePropertyChange("alignment", null, alignment.getSequences());
1249       }
1250     }
1251
1252     public void showSequence(int index)
1253     {
1254       Vector tmp = alignment.getHiddenSequences().showSequence(index);
1255       if(tmp.size()>0)
1256       {
1257         if(selectionGroup==null)
1258         {
1259           selectionGroup = new SequenceGroup();
1260           selectionGroup.setEndRes(alignment.getWidth()-1);
1261         }
1262
1263         for (int t = 0; t < tmp.size(); t++)
1264         {
1265           selectionGroup.addSequence(
1266               (SequenceI) tmp.elementAt(t), false
1267               );
1268         }
1269         firePropertyChange("alignment", null, alignment.getSequences());
1270       }
1271
1272       if(alignment.getHiddenSequences().getSize()<1)
1273         hasHiddenRows = false;
1274     }
1275
1276     public void showColumn(int col)
1277     {
1278       colSel.revealHiddenColumns(col);
1279       if(colSel.getHiddenColumns()==null)
1280         hasHiddenColumns = false;
1281     }
1282
1283     public void showAllHiddenColumns()
1284     {
1285       colSel.revealAllHiddenColumns();
1286       hasHiddenColumns = false;
1287     }
1288
1289     public void showAllHiddenSeqs()
1290     {
1291       if(alignment.getHiddenSequences().getSize()>0)
1292       {
1293         if(selectionGroup==null)
1294         {
1295           selectionGroup = new SequenceGroup();
1296           selectionGroup.setEndRes(alignment.getWidth()-1);
1297         }
1298         Vector tmp = alignment.getHiddenSequences().showAll();
1299         for(int t=0; t<tmp.size(); t++)
1300         {
1301           selectionGroup.addSequence(
1302               (SequenceI)tmp.elementAt(t), false
1303               );
1304         }
1305         firePropertyChange("alignment", null, alignment.getSequences());
1306         hasHiddenRows = false;
1307       }
1308     }
1309
1310     public void invertColumnSelection()
1311     {
1312       int column;
1313       for(int i=0; i<alignment.getWidth(); i++)
1314       {
1315         column = i;
1316
1317         if(colSel.contains(column))
1318           colSel.removeElement(column);
1319         else
1320           colSel.addElement(column);
1321
1322       }
1323
1324     }
1325
1326     public int adjustForHiddenSeqs(int alignmentIndex)
1327     {
1328       return alignment.getHiddenSequences().adjustForHiddenSeqs(alignmentIndex);
1329     }
1330
1331     /**
1332      * This method returns the a new SequenceI [] with
1333      * the selection sequence and start and end points adjusted
1334      * @return String[]
1335      */
1336     public SequenceI[] getSelectionAsNewSequence()
1337     {
1338       SequenceI[] sequences;
1339
1340       if (selectionGroup == null)
1341         sequences = alignment.getSequencesArray();
1342       else
1343         sequences = selectionGroup.getSelectionAsNewSequences(alignment);
1344
1345       return sequences;
1346     }
1347
1348     /**
1349      * This method returns the visible alignment as text, as
1350      * seen on the GUI, ie if columns are hidden they will not
1351      * be returned in the result.
1352      * Use this for calculating trees, PCA, redundancy etc on views
1353      * which contain hidden columns.
1354      * @return String[]
1355      */
1356     public jalview.datamodel.CigarArray getViewAsCigars(boolean selectedRegionOnly)
1357     {
1358       CigarArray selection=null;
1359       SequenceI [] seqs= null;
1360       int i, iSize;
1361       int start = 0, end = 0;
1362       if(selectedRegionOnly && selectionGroup!=null)
1363       {
1364         iSize = selectionGroup.getSize(false);
1365         seqs = selectionGroup.getSequencesInOrder(alignment);
1366         start = selectionGroup.getStartRes();
1367         end = selectionGroup.getEndRes(); // inclusive for start and end in SeqCigar constructor
1368       }
1369       else
1370       {
1371         iSize = alignment.getHeight();
1372         seqs = alignment.getSequencesArray();
1373         end = alignment.getWidth()-1;
1374       }
1375       SeqCigar[] selseqs = new SeqCigar[iSize];
1376       for(i=0; i<iSize; i++)
1377       {
1378         selseqs[i] = new SeqCigar(seqs[i], start, end);
1379       }
1380       selection=new CigarArray(selseqs);
1381       // now construct the CigarArray operations
1382       if (hasHiddenColumns) {
1383         Vector regions = colSel.getHiddenColumns();
1384         int [] region;
1385         int hideStart, hideEnd;
1386         int last=start;
1387         for (int j = 0; last<end & j < regions.size(); j++)
1388         {
1389           region = (int[]) regions.elementAt(j);
1390           hideStart = region[0];
1391           hideEnd = region[1];
1392           // edit hidden regions to selection range
1393           if(hideStart<last) {
1394             if (hideEnd > last)
1395             {
1396               hideStart = last;
1397             } else
1398               continue;
1399           }
1400
1401           if (hideStart>end)
1402             break;
1403
1404           if (hideEnd>end)
1405             hideEnd=end;
1406
1407           if (hideStart>hideEnd)
1408             break;
1409           /**
1410            * form operations...
1411            */
1412           if (last<hideStart)
1413             selection.addOperation(CigarArray.M, hideStart-last);
1414           selection.addOperation(CigarArray.D, 1+hideEnd-hideStart);
1415           last = hideEnd+1;
1416         }
1417         // Final match if necessary.
1418         if (last<end)
1419           selection.addOperation(CigarArray.M, end-last+1);
1420       } else {
1421         selection.addOperation(CigarArray.M, end-start+1);
1422       }
1423       return selection;
1424     }
1425     /**
1426      * return a compact representation of the current alignment selection to
1427      * pass to an analysis function
1428      * @param selectedOnly boolean true to just return the selected view
1429      * @return AlignmentView
1430      */
1431     jalview.datamodel.AlignmentView getAlignmentView(boolean selectedOnly) {
1432       // JBPNote:
1433       // this is here because the AlignmentView constructor modifies the CigarArray
1434       // object. Refactoring of Cigar and alignment view representation should
1435       // be done to remove redundancy.
1436       CigarArray aligview = getViewAsCigars(selectedOnly);
1437       if (aligview!=null) {
1438         return new AlignmentView(aligview,
1439             (selectedOnly && selectionGroup!=null) ? selectionGroup.getStartRes() : 0);
1440       }
1441       return null;
1442     }
1443     /**
1444      * This method returns the visible alignment as text, as
1445      * seen on the GUI, ie if columns are hidden they will not
1446      * be returned in the result.
1447      * Use this for calculating trees, PCA, redundancy etc on views
1448      * which contain hidden columns.
1449      * @return String[]
1450      */
1451     public String [] getViewAsString(boolean selectedRegionOnly)
1452     {
1453       String [] selection = null;
1454       SequenceI [] seqs= null;
1455       int i, iSize;
1456       int start = 0, end = 0;
1457       if(selectedRegionOnly && selectionGroup!=null)
1458       {
1459         iSize = selectionGroup.getSize(false);
1460         seqs = selectionGroup.getSequencesInOrder(alignment);
1461         start = selectionGroup.getStartRes();
1462         end = selectionGroup.getEndRes()+1;
1463       }
1464       else
1465       {
1466         iSize = alignment.getHeight();
1467         seqs = alignment.getSequencesArray();
1468         end = alignment.getWidth();
1469       }
1470
1471       selection = new String[iSize];
1472       if (hasHiddenColumns) {
1473         selection = colSel.getVisibleSequenceStrings(start, end, seqs);
1474       } else {
1475         for(i=0; i<iSize; i++)
1476         {
1477           selection[i] = seqs[i].getSequence(start, end);
1478         }
1479
1480       }
1481       return selection;
1482     }
1483
1484     public boolean getShowHiddenMarkers()
1485     {
1486       return showHiddenMarkers;
1487     }
1488
1489     public void setShowHiddenMarkers(boolean show)
1490     {
1491       showHiddenMarkers = show;
1492     }
1493
1494     public String getSequenceSetId()
1495     {
1496       if(sequenceSetID==null)
1497         sequenceSetID =  alignment.hashCode()+"";
1498
1499       return sequenceSetID;
1500     }
1501
1502 }