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