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