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