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