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