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