Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 14:43:25 GMT
  2. Package jalview.viewmodel

File AlignmentViewport.java

 

Coverage histogram

../../img/srcFileCovDistChart8.png
20% of files have more coverage

Code metrics

372
867
286
1
3,860
2,641
531
0.61
3.03
286
1.86

Classes

Class Line # Actions
AlignmentViewport 110 867 531
0.7676%
 

Contributing tests

This file is covered by 545 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.viewmodel;
22   
23    import java.awt.Color;
24    import java.beans.PropertyChangeSupport;
25    import java.util.ArrayDeque;
26    import java.util.ArrayList;
27    import java.util.BitSet;
28    import java.util.Deque;
29    import java.util.HashMap;
30    import java.util.Hashtable;
31    import java.util.Iterator;
32    import java.util.List;
33    import java.util.Map;
34   
35    import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
36    import jalview.analysis.AlignmentUtils;
37    import jalview.analysis.Conservation;
38    import jalview.analysis.TreeModel;
39    import jalview.api.AlignCalcManagerI2;
40    import jalview.api.AlignCalcWorkerI;
41    import jalview.api.AlignExportSettingsI;
42    import jalview.api.AlignViewportI;
43    import jalview.api.AlignmentViewPanel;
44    import jalview.api.FeaturesDisplayedI;
45    import jalview.api.ViewStyleI;
46    import jalview.bin.Console;
47    import jalview.commands.CommandI;
48    import jalview.datamodel.AlignedCodonFrame;
49    import jalview.datamodel.AlignmentAnnotation;
50    import jalview.datamodel.AlignmentExportData;
51    import jalview.datamodel.AlignmentI;
52    import jalview.datamodel.AlignmentView;
53    import jalview.datamodel.Annotation;
54    import jalview.datamodel.ColumnSelection;
55    import jalview.datamodel.ContactListI;
56    import jalview.datamodel.ContactMatrixI;
57    import jalview.datamodel.HiddenColumns;
58    import jalview.datamodel.HiddenSequences;
59    import jalview.datamodel.ProfilesI;
60    import jalview.datamodel.SearchResultsI;
61    import jalview.datamodel.Sequence;
62    import jalview.datamodel.SequenceCollectionI;
63    import jalview.datamodel.SequenceGroup;
64    import jalview.datamodel.SequenceI;
65    import jalview.gui.QuitHandler;
66    import jalview.project.Jalview2XML;
67    import jalview.renderer.ResidueShader;
68    import jalview.renderer.ResidueShaderI;
69    import jalview.schemes.ColourSchemeI;
70    import jalview.structure.CommandListener;
71    import jalview.structure.StructureSelectionManager;
72    import jalview.structure.VamsasSource;
73    import jalview.util.Comparison;
74    import jalview.util.Constants;
75    import jalview.util.MapList;
76    import jalview.util.MappingUtils;
77    import jalview.util.MessageManager;
78    import jalview.viewmodel.styles.ViewStyle;
79    import jalview.workers.AlignCalcManager2;
80    import jalview.workers.ComplementConsensusThread;
81    import jalview.workers.ConsensusThread;
82    import jalview.workers.SecondaryStructureConsensusThread;
83    import jalview.workers.InformationThread;
84    import jalview.workers.StrucConsensusThread;
85   
86    import java.awt.Color;
87    import java.beans.PropertyChangeSupport;
88    import java.util.ArrayDeque;
89    import java.util.ArrayList;
90    import java.util.BitSet;
91    import java.util.Deque;
92    import java.util.HashMap;
93    import java.util.Hashtable;
94    import java.util.Iterator;
95    import java.util.List;
96    import java.util.Map;
97    import java.util.concurrent.Executors;
98    import java.util.concurrent.ScheduledExecutorService;
99    import java.util.concurrent.ScheduledThreadPoolExecutor;
100   
101    /**
102    * base class holding visualization and analysis attributes and common logic for
103    * an active alignment view displayed in the GUI
104    *
105    * @author jimp
106    *
107    * @param <AlignmentPanelT>
108    * implementation of the AlignmentViewPanel used by the class
109    */
 
110    public abstract class AlignmentViewport<AlignmentPanelT extends AlignmentViewPanel>
111    implements AlignViewportI, CommandListener, VamsasSource
112    {
113    public static final String PROPERTY_ALIGNMENT = "alignment";
114    public static final String PROPERTY_SEQUENCE = "sequence";
115    protected ViewportRanges ranges;
116   
117    protected ViewStyleI viewStyle = new ViewStyle();
118   
119    /**
120    * A viewport that hosts the cDna view of this (protein), or vice versa (if
121    * set).
122    */
123    AlignViewportI codingComplement = null;
124   
125    FeaturesDisplayedI featuresDisplayed = null;
126   
127    protected Deque<CommandI> historyList = new ArrayDeque<>();
128   
129    protected Deque<CommandI> redoList = new ArrayDeque<>();
130   
131    /**
132    * used to determine if quit should be confirmed
133    */
134    private boolean savedUpToDate = false;
135   
136    /**
137    * alignment displayed in the viewport. Please use get/setter
138    */
139    protected AlignmentI alignment;
140   
141    /*
142    * probably unused indicator that view is of a dataset rather than an
143    * alignment
144    */
145   
146    protected boolean ignoreBelowBackGroundFrequencyCalculation = false;
147   
148    protected boolean infoLetterHeight = false;
149   
150    protected AlignmentAnnotation occupancy;
151   
152    /**
153    * results of alignment consensus analysis for visible portion of view
154    */
155    protected ProfilesI consensusProfiles;
156   
157    /**
158    * HMM profile for the alignment
159    */
160    protected ProfilesI hmmProfiles;
161   
 
162  595 toggle public AlignmentViewport(AlignmentI al)
163    {
164  595 setAlignment(al);
165  595 ranges = new ViewportRanges(al);
166    }
167   
168    protected AlignmentPanelT alignPanel = null;
169   
 
170  513 toggle public void setAlignPanel(AlignmentPanelT ap)
171    {
172  513 alignPanel = ap;
173    }
174   
175    /**
176    * return the AlignmentViewPanel containing the given viewport. Use this to
177    * get the components currently handling the given viewport.
178    *
179    * @param av
180    * @return null or an alignPanel guaranteed to have non-null alignFrame
181    * reference
182    */
 
183  10442 toggle public AlignmentPanelT getAlignPanel()
184    {
185  10442 return alignPanel;
186    }
187   
188    /**
189    * @param name
190    * @see jalview.api.ViewStyleI#setFontName(java.lang.String)
191    */
 
192  0 toggle @Override
193    public void setFontName(String name)
194    {
195  0 viewStyle.setFontName(name);
196    }
197   
198    /**
199    * @param style
200    * @see jalview.api.ViewStyleI#setFontStyle(int)
201    */
 
202  0 toggle @Override
203    public void setFontStyle(int style)
204    {
205  0 viewStyle.setFontStyle(style);
206    }
207   
208    /**
209    * @param size
210    * @see jalview.api.ViewStyleI#setFontSize(int)
211    */
 
212  0 toggle @Override
213    public void setFontSize(int size)
214    {
215  0 viewStyle.setFontSize(size);
216    }
217   
218    /**
219    * @return
220    * @see jalview.api.ViewStyleI#getFontStyle()
221    */
 
222  0 toggle @Override
223    public int getFontStyle()
224    {
225  0 return viewStyle.getFontStyle();
226    }
227   
228    /**
229    * @return
230    * @see jalview.api.ViewStyleI#getFontName()
231    */
 
232  0 toggle @Override
233    public String getFontName()
234    {
235  0 return viewStyle.getFontName();
236    }
237   
238    /**
239    * @return
240    * @see jalview.api.ViewStyleI#getFontSize()
241    */
 
242  0 toggle @Override
243    public int getFontSize()
244    {
245  0 return viewStyle.getFontSize();
246    }
247   
248    /**
249    * @param upperCasebold
250    * @see jalview.api.ViewStyleI#setUpperCasebold(boolean)
251    */
 
252  0 toggle @Override
253    public void setUpperCasebold(boolean upperCasebold)
254    {
255  0 viewStyle.setUpperCasebold(upperCasebold);
256    }
257   
258    /**
259    * @return
260    * @see jalview.api.ViewStyleI#isUpperCasebold()
261    */
 
262  0 toggle @Override
263    public boolean isUpperCasebold()
264    {
265  0 return viewStyle.isUpperCasebold();
266    }
267   
268    /**
269    * @return
270    * @see jalview.api.ViewStyleI#isSeqNameItalics()
271    */
 
272  2487 toggle @Override
273    public boolean isSeqNameItalics()
274    {
275  2487 return viewStyle.isSeqNameItalics();
276    }
277   
278    /**
279    * @param colourByReferenceSeq
280    * @see jalview.api.ViewStyleI#setColourByReferenceSeq(boolean)
281    */
 
282  10 toggle @Override
283    public void setColourByReferenceSeq(boolean colourByReferenceSeq)
284    {
285  10 viewStyle.setColourByReferenceSeq(colourByReferenceSeq);
286    }
287   
288    /**
289    * @param b
290    * @see jalview.api.ViewStyleI#setColourAppliesToAllGroups(boolean)
291    */
 
292  802 toggle @Override
293    public void setColourAppliesToAllGroups(boolean b)
294    {
295  802 viewStyle.setColourAppliesToAllGroups(b);
296    }
297   
298    /**
299    * @return
300    * @see jalview.api.ViewStyleI#getColourAppliesToAllGroups()
301    */
 
302  1027 toggle @Override
303    public boolean getColourAppliesToAllGroups()
304    {
305  1027 return viewStyle.getColourAppliesToAllGroups();
306    }
307   
308    /**
309    * @return
310    * @see jalview.api.ViewStyleI#getAbovePIDThreshold()
311    */
 
312  939 toggle @Override
313    public boolean getAbovePIDThreshold()
314    {
315  939 return viewStyle.getAbovePIDThreshold();
316    }
317   
 
318  939 toggle @Override
319    public boolean getByConsensusSecondaryStructureSelected()
320    {
321  939 return viewStyle.getByConsensusSecondaryStructureSelected();
322    }
323   
 
324  96 toggle public void setShowStructureProvider(boolean b)
325    {
326  96 viewStyle.setShowStructureProvider(b);
327    }
328   
 
329  5911 toggle public boolean isShowStructureProvider()
330    {
331  5911 return viewStyle.isShowStructureProvider();
332    }
333   
334    /**
335    * @param inc
336    * @see jalview.api.ViewStyleI#setIncrement(int)
337    */
 
338  96 toggle @Override
339    public void setIncrement(int inc)
340    {
341  96 viewStyle.setIncrement(inc);
342    }
343   
344    /**
345    * @return
346    * @see jalview.api.ViewStyleI#getIncrement()
347    */
 
348  0 toggle @Override
349    public int getIncrement()
350    {
351  0 return viewStyle.getIncrement();
352    }
353   
354    /**
355    * @param inc
356    * @see jalview.api.ViewStyleI#setConsensusSecondaryStructureThreshold(int)
357    */
 
358  96 toggle @Override
359    public void setConsensusSecondaryStructureThreshold(int val)
360    {
361  96 viewStyle.setConsensusSecondaryStructureThreshold(val);
362    }
363   
364    /**
365    * @return
366    * @see jalview.api.ViewStyleI#getConsensusSecondaryStructureThreshold()
367    */
 
368  0 toggle @Override
369    public int getConsensusSecondaryStructureThreshold()
370    {
371  0 return viewStyle.getConsensusSecondaryStructureThreshold();
372    }
373   
374    /**
375    * @param b
376    * @see jalview.api.ViewStyleI#setConservationSelected(boolean)
377    */
 
378  104 toggle @Override
379    public void setConservationSelected(boolean b)
380    {
381  104 viewStyle.setConservationSelected(b);
382    }
383   
384    /**
385    * @param show
386    * @see jalview.api.ViewStyleI#setShowHiddenMarkers(boolean)
387    */
 
388  0 toggle @Override
389    public void setShowHiddenMarkers(boolean show)
390    {
391  0 viewStyle.setShowHiddenMarkers(show);
392    }
393   
394    /**
395    * @return
396    * @see jalview.api.ViewStyleI#getShowHiddenMarkers()
397    */
 
398  1473 toggle @Override
399    public boolean getShowHiddenMarkers()
400    {
401  1473 return viewStyle.getShowHiddenMarkers();
402    }
403   
404    /**
405    * @param b
406    * @see jalview.api.ViewStyleI#setScaleRightWrapped(boolean)
407    */
 
408  9 toggle @Override
409    public void setScaleRightWrapped(boolean b)
410    {
411  9 viewStyle.setScaleRightWrapped(b);
412    }
413   
414    /**
415    * @param b
416    * @see jalview.api.ViewStyleI#setScaleLeftWrapped(boolean)
417    */
 
418  11 toggle @Override
419    public void setScaleLeftWrapped(boolean b)
420    {
421  11 viewStyle.setScaleLeftWrapped(b);
422    }
423   
424    /**
425    * @param b
426    * @see jalview.api.ViewStyleI#setScaleAboveWrapped(boolean)
427    */
 
428  14 toggle @Override
429    public void setScaleAboveWrapped(boolean b)
430    {
431  14 viewStyle.setScaleAboveWrapped(b);
432    }
433   
434    /**
435    * @return
436    * @see jalview.api.ViewStyleI#getScaleLeftWrapped()
437    */
 
438  2690 toggle @Override
439    public boolean getScaleLeftWrapped()
440    {
441  2690 return viewStyle.getScaleLeftWrapped();
442    }
443   
444    /**
445    * @return
446    * @see jalview.api.ViewStyleI#getScaleAboveWrapped()
447    */
 
448  2172 toggle @Override
449    public boolean getScaleAboveWrapped()
450    {
451  2172 return viewStyle.getScaleAboveWrapped();
452    }
453   
454    /**
455    * @return
456    * @see jalview.api.ViewStyleI#getScaleRightWrapped()
457    */
 
458  3572 toggle @Override
459    public boolean getScaleRightWrapped()
460    {
461  3572 return viewStyle.getScaleRightWrapped();
462    }
463   
464    /**
465    * @param b
466    * @see jalview.api.ViewStyleI#setAbovePIDThreshold(boolean)
467    */
 
468  105 toggle @Override
469    public void setAbovePIDThreshold(boolean b)
470    {
471  105 viewStyle.setAbovePIDThreshold(b);
472    }
473   
 
474  96 toggle @Override
475    public void setByConsensusSecondaryStructureSelected(boolean b)
476    {
477  96 viewStyle.setByConsensusSecondaryStructureSelected(b);
478    }
479   
480    /**
481    * @param thresh
482    * @see jalview.api.ViewStyleI#setThreshold(int)
483    */
 
484  117 toggle @Override
485    public void setThreshold(int thresh)
486    {
487  117 viewStyle.setThreshold(thresh);
488    }
489   
490    /**
491    * @return
492    * @see jalview.api.ViewStyleI#getThreshold()
493    */
 
494  0 toggle @Override
495    public int getThreshold()
496    {
497  0 return viewStyle.getThreshold();
498    }
499   
500    /**
501    * @return
502    * @see jalview.api.ViewStyleI#getShowJVSuffix()
503    */
 
504  19415 toggle @Override
505    public boolean getShowJVSuffix()
506    {
507  19415 return viewStyle.getShowJVSuffix();
508    }
509   
510    /**
511    * @param b
512    * @see jalview.api.ViewStyleI#setShowJVSuffix(boolean)
513    */
 
514  97 toggle @Override
515    public void setShowJVSuffix(boolean b)
516    {
517  97 viewStyle.setShowJVSuffix(b);
518    }
519   
520    /**
521    * @param state
522    * @see jalview.api.ViewStyleI#setWrapAlignment(boolean)
523    */
 
524  113 toggle @Override
525    public void setWrapAlignment(boolean state)
526    {
527  113 viewStyle.setWrapAlignment(state);
528  113 ranges.setWrappedMode(state);
529    }
530   
531    /**
532    * @param state
533    * @see jalview.api.ViewStyleI#setShowText(boolean)
534    */
 
535  96 toggle @Override
536    public void setShowText(boolean state)
537    {
538  96 viewStyle.setShowText(state);
539    }
540   
541    /**
542    * @param state
543    * @see jalview.api.ViewStyleI#setRenderGaps(boolean)
544    */
 
545  96 toggle @Override
546    public void setRenderGaps(boolean state)
547    {
548  96 viewStyle.setRenderGaps(state);
549    }
550   
551    /**
552    * @return
553    * @see jalview.api.ViewStyleI#getColourText()
554    */
 
555  789457 toggle @Override
556    public boolean getColourText()
557    {
558  789458 return viewStyle.getColourText();
559    }
560   
561    /**
562    * @param state
563    * @see jalview.api.ViewStyleI#setColourText(boolean)
564    */
 
565  96 toggle @Override
566    public void setColourText(boolean state)
567    {
568  96 viewStyle.setColourText(state);
569    }
570   
571    /**
572    * @return
573    * @see jalview.api.ViewStyleI#getWrapAlignment()
574    */
 
575  26336 toggle @Override
576    public boolean getWrapAlignment()
577    {
578  26336 return viewStyle.getWrapAlignment();
579    }
580   
581    /**
582    * @return
583    * @see jalview.api.ViewStyleI#getShowText()
584    */
 
585  790194 toggle @Override
586    public boolean getShowText()
587    {
588  790194 return viewStyle.getShowText();
589    }
590   
591    /**
592    * @return
593    * @see jalview.api.ViewStyleI#getWrappedWidth()
594    */
 
595  3 toggle @Override
596    public int getWrappedWidth()
597    {
598  3 return viewStyle.getWrappedWidth();
599    }
600   
601    /**
602    * @param w
603    * @see jalview.api.ViewStyleI#setWrappedWidth(int)
604    */
 
605  702 toggle @Override
606    public void setWrappedWidth(int w)
607    {
608  702 viewStyle.setWrappedWidth(w);
609    }
610   
611    /**
612    * @return
613    * @see jalview.api.ViewStyleI#getCharHeight()
614    */
 
615  103221 toggle @Override
616    public int getCharHeight()
617    {
618  103221 return viewStyle.getCharHeight();
619    }
620   
621    /**
622    * @param h
623    * @see jalview.api.ViewStyleI#setCharHeight(int)
624    */
 
625  699 toggle @Override
626    public void setCharHeight(int h)
627    {
628  699 viewStyle.setCharHeight(h);
629    }
630   
631    /**
632    * @return
633    * @see jalview.api.ViewStyleI#getCharWidth()
634    */
 
635  1713463 toggle @Override
636    public int getCharWidth()
637    {
638  1713465 return viewStyle.getCharWidth();
639    }
640   
641    /**
642    * @param w
643    * @see jalview.api.ViewStyleI#setCharWidth(int)
644    */
 
645  702 toggle @Override
646    public void setCharWidth(int w)
647    {
648  702 viewStyle.setCharWidth(w);
649    }
650   
651    /**
652    * @return
653    * @see jalview.api.ViewStyleI#getShowBoxes()
654    */
 
655  922646 toggle @Override
656    public boolean getShowBoxes()
657    {
658  922649 return viewStyle.getShowBoxes();
659    }
660   
661    /**
662    * @return
663    * @see jalview.api.ViewStyleI#getShowUnconserved()
664    */
 
665  788608 toggle @Override
666    public boolean getShowUnconserved()
667    {
668  788610 return viewStyle.getShowUnconserved();
669    }
670   
671    /**
672    * @param showunconserved
673    * @see jalview.api.ViewStyleI#setShowUnconserved(boolean)
674    */
 
675  96 toggle @Override
676    public void setShowUnconserved(boolean showunconserved)
677    {
678  96 viewStyle.setShowUnconserved(showunconserved);
679    }
680   
681    /**
682    * @param default1
683    * @see jalview.api.ViewStyleI#setSeqNameItalics(boolean)
684    */
 
685  0 toggle @Override
686    public void setSeqNameItalics(boolean default1)
687    {
688  0 viewStyle.setSeqNameItalics(default1);
689    }
690   
 
691  378988 toggle @Override
692    public AlignmentI getAlignment()
693    {
694  378992 return alignment;
695    }
696   
 
697  0 toggle @Override
698    public char getGapCharacter()
699    {
700  0 return alignment.getGapCharacter();
701    }
702   
703    protected String sequenceSetID;
704   
705    /**
706    * probably unused indicator that view is of a dataset rather than an
707    * alignment
708    */
709    protected boolean isDataset = false;
710   
711   
 
712  0 toggle public void setDataset(boolean b)
713    {
714  0 isDataset = b;
715    }
716   
 
717  513 toggle public boolean isDataset()
718    {
719  513 return isDataset;
720    }
721   
722    private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
723   
724    protected ColumnSelection colSel = new ColumnSelection();
725   
726    protected boolean autoCalculateConsensusAndConservation = true;
727   
 
728  729 toggle public boolean getAutoCalculateConsensusAndConservation()
729    { // BH 2019.07.24
730  729 return autoCalculateConsensusAndConservation;
731    }
732   
 
733  0 toggle public void setAutoCalculateConsensusAndConservation(boolean b)
734    {
735  0 autoCalculateConsensusAndConservation = b;
736    }
737   
738    protected boolean autoCalculateStrucConsensus = true;
739   
 
740  0 toggle public boolean getAutoCalculateStrucConsensus()
741    { // BH 2019.07.24
742  0 return autoCalculateStrucConsensus;
743    }
744   
 
745  0 toggle public void setAutoCalculateStrucConsensus(boolean b)
746    {
747  0 autoCalculateStrucConsensus = b;
748    }
749    protected boolean ignoreGapsInConsensusCalculation = false;
750   
751    protected ResidueShaderI residueShading = new ResidueShader();
752   
753   
 
754  282 toggle @Override
755    public void setGlobalColourScheme(ColourSchemeI cs)
756    {
757    // TODO: logic refactored from AlignFrame changeColour -
758    // TODO: autorecalc stuff should be changed to rely on the worker system
759    // check to see if we should implement a changeColour(cs) method rather than
760    // put the logic in here
761    // - means that caller decides if they want to just modify state and defer
762    // calculation till later or to do all calculations in thread.
763    // via changecolour
764   
765    /*
766    * only instantiate alignment colouring once, thereafter update it;
767    * this means that any conservation or PID threshold settings
768    * persist when the alignment colour scheme is changed
769    */
770  282 if (residueShading == null)
771    {
772  0 residueShading = new ResidueShader(viewStyle);
773    }
774  282 residueShading.setColourScheme(cs);
775   
776    // TODO: do threshold and increment belong in ViewStyle or ResidueShader?
777    // ...problem: groups need these, but do not currently have a ViewStyle
778   
779  282 if (cs != null)
780    {
781  88 if (getConservationSelected())
782    {
783  15 residueShading.setConservation(hconservation);
784    }
785    /*
786    * reset conservation flag in case just set to false if
787    * Conservation was null (calculation still in progress)
788    */
789  88 residueShading.setConservationApplied(getConservationSelected());
790  88 residueShading.alignmentChanged(alignment, hiddenRepSequences);
791    }
792   
793    /*
794    * if 'apply colour to all groups' is selected... do so
795    * (but don't transfer any colour threshold settings to groups)
796    */
797  282 if (getColourAppliesToAllGroups())
798    {
799  72 for (SequenceGroup sg : getAlignment().getGroups())
800    {
801    /*
802    * retain any colour thresholds per group while
803    * changing choice of colour scheme (JAL-2386)
804    */
805  9 sg.setColourScheme(
806  9 cs == null ? null : cs.getInstance(this, sg));
807  9 if (cs != null)
808    {
809  8 sg.getGroupColourScheme().alignmentChanged(sg,
810    hiddenRepSequences);
811    }
812    }
813    }
814    }
815   
 
816  1492 toggle @Override
817    public ColourSchemeI getGlobalColourScheme()
818    {
819  1492 return residueShading == null ? null : residueShading.getColourScheme();
820    }
821   
 
822  927855 toggle @Override
823    public ResidueShaderI getResidueShading()
824    {
825  927856 return residueShading;
826    }
827   
828   
829    protected AlignmentAnnotation consensus;
830   
831    protected List<AlignmentAnnotation> secondaryStructureConsensus;
832   
833    protected AlignmentAnnotation complementConsensus;
834   
835    protected AlignmentAnnotation gapcounts;
836   
837    protected AlignmentAnnotation strucConsensus;
838   
839    protected AlignmentAnnotation conservation;
840   
841    protected AlignmentAnnotation quality;
842   
843    protected AlignmentAnnotation[] groupConsensus;
844   
845    protected AlignmentAnnotation[] groupSSConsensus;
846   
847    protected AlignmentAnnotation[] groupConservation;
848   
849    /**
850    * results of alignment consensus analysis for visible portion of view
851    */
852    protected ProfilesI hconsensus = null;
853   
854    protected Map<String, ProfilesI> hSSConsensusProfileMap = null;
855   
856   
857    /**
858    * results of cDNA complement consensus visible portion of view
859    */
860    protected Hashtable<String, Object>[] hcomplementConsensus = null;
861   
862    /**
863    * results of secondary structure base pair consensus for visible portion of
864    * view
865    */
866    protected Hashtable<String, Object>[] hStrucConsensus = null;
867   
868    protected Conservation hconservation = null;
869   
870   
 
871  855 toggle @Override
872    public void setConservation(Conservation cons)
873    {
874  855 hconservation = cons;
875    }
876   
 
877  1768 toggle @Override
878    public List<String> getSecondaryStructureSources()
879    {
880  1768 return viewStyle.getSecondaryStructureSources();
881    }
882   
 
883  3046 toggle @Override
884    public void setSecondaryStructureSources(
885    List<String> secondaryStructureSources)
886    {
887  3046 viewStyle.setSecondaryStructureSources(secondaryStructureSources);
888    }
889   
 
890  595 toggle protected void setSecondaryStructureSources(AlignmentAnnotation[] aa)
891    {
892  595 List<String> sources = null;
893   
894  595 if (aa != null)
895    {
896  494 sources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(aa);
897  494 if (sources != null)
898    {
899  494 sources.add(0, Constants.SS_ALL_PROVIDERS);
900  494 viewStyle.setSecondaryStructureSources(sources);
901    }
902    }
903    }
904   
905    /**
906    * percentage gaps allowed in a column before all amino acid properties should
907    * be considered unconserved
908    */
909    int ConsPercGaps = 25; // JBPNote : This should be a scalable property!
910   
 
911  1738 toggle @Override
912    public int getConsPercGaps()
913    {
914  1738 return ConsPercGaps;
915    }
916   
 
917  922 toggle @Override
918    public void setSequenceConsensusHash(ProfilesI hconsensus)
919    {
920  922 this.hconsensus = hconsensus;
921    }
922   
 
923  1173 toggle @Override
924    public void setSequenceSSConsensusHash(
925    Map<String, ProfilesI> hSSConsensusProfileMap)
926    {
927  1173 this.hSSConsensusProfileMap = hSSConsensusProfileMap;
928    }
929   
 
930  3 toggle @Override
931    public void setComplementConsensusHash(
932    Hashtable<String, Object>[] hconsensus)
933    {
934  3 this.hcomplementConsensus = hconsensus;
935    }
936   
 
937  4240 toggle @Override
938    public ProfilesI getSequenceConsensusHash()
939    {
940  4240 return hconsensus;
941    }
942   
 
943  4491 toggle @Override
944    public Map<String, ProfilesI> getSequenceSSConsensusHash()
945    {
946  4491 return hSSConsensusProfileMap;
947    }
948   
 
949  3 toggle @Override
950    public void setHmmProfiles(ProfilesI info)
951    {
952  3 hmmProfiles = info;
953    }
954   
 
955  3 toggle @Override
956    public ProfilesI getHmmProfiles()
957    {
958  3 return hmmProfiles;
959    }
960   
 
961  3205 toggle @Override
962    public Hashtable<String, Object>[] getComplementConsensusHash()
963    {
964  3205 return hcomplementConsensus;
965    }
966   
 
967  3204 toggle @Override
968    public Hashtable<String, Object>[] getRnaStructureConsensusHash()
969    {
970  3204 return hStrucConsensus;
971    }
972   
 
973  2 toggle @Override
974    public void setRnaStructureConsensusHash(
975    Hashtable<String, Object>[] hStrucConsensus)
976    {
977  2 this.hStrucConsensus = hStrucConsensus;
978   
979    }
980   
 
981  1611 toggle @Override
982    public AlignmentAnnotation getAlignmentQualityAnnot()
983    {
984  1611 return quality;
985    }
986   
 
987  2467 toggle @Override
988    public AlignmentAnnotation getAlignmentConservationAnnotation()
989    {
990  2467 return conservation;
991    }
992   
 
993  6647 toggle @Override
994    public AlignmentAnnotation getAlignmentConsensusAnnotation()
995    {
996  6647 return consensus;
997    }
998   
 
999  6741 toggle @Override
1000    public List<AlignmentAnnotation> getAlignmentSecondaryStructureConsensusAnnotation()
1001    {
1002  6741 return secondaryStructureConsensus;
1003    }
1004   
 
1005  2776 toggle @Override
1006    public AlignmentAnnotation getAlignmentGapAnnotation()
1007    {
1008  2776 return gapcounts;
1009    }
1010   
 
1011  3211 toggle @Override
1012    public AlignmentAnnotation getComplementConsensusAnnotation()
1013    {
1014  3211 return complementConsensus;
1015    }
1016   
 
1017  3204 toggle @Override
1018    public AlignmentAnnotation getAlignmentStrucConsensusAnnotation()
1019    {
1020  3204 return strucConsensus;
1021    }
1022   
1023    protected AlignCalcManagerI2 calculator = new AlignCalcManager2();
1024   
1025    /**
1026    * trigger update of conservation annotation
1027    */
 
1028  1065 toggle public void updateConservation(final AlignmentViewPanel ap)
1029    {
1030    // see note in mantis : issue number 8585
1031  1065 if (alignment.isNucleotide()
1032    || (conservation == null && quality == null)
1033    || !autoCalculateConsensusAndConservation)
1034    {
1035  286 return;
1036    }
1037  779 if (calculator.getWorkersOfClass(
1038    jalview.workers.ConservationThread.class).isEmpty())
1039    {
1040  401 calculator.registerWorker(
1041    new jalview.workers.ConservationThread(this, ap));
1042    }
1043    }
1044   
1045    /**
1046    * trigger update of consensus annotation
1047    */
 
1048  1424 toggle public void updateConsensus(final AlignmentViewPanel ap)
1049    {
1050    // see note in mantis : issue number 8585
1051  1424 if (consensus == null || !autoCalculateConsensusAndConservation)
1052    {
1053  0 return;
1054    }
1055  1424 if (calculator.getWorkersOfClass(ConsensusThread.class).isEmpty())
1056    {
1057  482 calculator.registerWorker(new ConsensusThread(this, ap));
1058    }
1059   
1060    /*
1061    * A separate thread to compute cDNA consensus for a protein alignment
1062    * which has mapping to cDNA
1063    */
1064  1424 final AlignmentI al = this.getAlignment();
1065  1424 if (!al.isNucleotide() && al.getCodonFrames() != null
1066    && !al.getCodonFrames().isEmpty())
1067    {
1068    /*
1069    * fudge - check first for protein-to-nucleotide mappings
1070    * (we don't want to do this for protein-to-protein)
1071    */
1072  5 boolean doConsensus = false;
1073  5 for (AlignedCodonFrame mapping : al.getCodonFrames())
1074    {
1075    // TODO hold mapping type e.g. dna-to-protein in AlignedCodonFrame?
1076  5 MapList[] mapLists = mapping.getdnaToProt();
1077    // mapLists can be empty if project load has not finished resolving seqs
1078  5 if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
1079    {
1080  5 doConsensus = true;
1081  5 break;
1082    }
1083    }
1084  5 if (doConsensus)
1085    {
1086  5 if (calculator.getWorkersOfClass(ComplementConsensusThread.class).isEmpty())
1087    {
1088  4 calculator.registerWorker(new ComplementConsensusThread(this, ap));
1089    }
1090    }
1091    }
1092    }
1093   
1094    /**
1095    * trigger update of Secondary Structure consensus annotation
1096    */
 
1097  1873 toggle public void updateSecondaryStructureConsensus(final AlignmentViewPanel ap)
1098    {
1099    // see note in mantis : issue number 8585
1100  1873 if (secondaryStructureConsensus == null || !autoCalculateConsensusAndConservation)
1101    {
1102  0 return;
1103    }
1104  1873 setSecondaryStructureSources();
1105  1873 List<String> ssSources = viewStyle.getSecondaryStructureSources();
1106  1873 if (secondaryStructureConsensus.size() != ssSources.size())
1107    {
1108   
1109  93 for (String source : ssSources)
1110    {
1111  108 boolean ssConsensusForSourcePresent = false;
1112  108 for (AlignmentAnnotation aa : secondaryStructureConsensus)
1113    {
1114  30 if (aa.description.startsWith(source))
1115    {
1116  15 ssConsensusForSourcePresent = true;
1117  15 break;
1118    }
1119    }
1120   
1121  108 if (!ssConsensusForSourcePresent)
1122    {
1123  93 AlignmentAnnotation ssConsensus = new AlignmentAnnotation(
1124    MessageManager.getString("label.ssconsensus_label") + " "
1125    + source,
1126    source + " "
1127    + MessageManager
1128    .getString("label.ssconsensus_descr"),
1129    new Annotation[1], 0f, 100f,
1130    AlignmentAnnotation.BAR_GRAPH);
1131   
1132  93 ssConsensus.hasText = true;
1133  93 ssConsensus.autoCalculated = true;
1134  93 secondaryStructureConsensus.add(ssConsensus);
1135  93 if (showSSConsensus)
1136    {
1137  0 alignment.addAnnotation(ssConsensus);
1138   
1139    }
1140    }
1141    }
1142    }
1143  1873 List<AlignCalcWorkerI> ssworkers = calculator.getWorkersOfClass(
1144    SecondaryStructureConsensusThread.class);
1145  1873 if (ssworkers == null || ssworkers.isEmpty())
1146    {
1147  482 calculator.registerWorker(
1148    new SecondaryStructureConsensusThread(this, ap));
1149    } else {
1150  1391 calculator.startWorker(ssworkers.get(0));
1151    }
1152  1873 ap.adjustAnnotationHeight();
1153   
1154    }
1155   
 
1156  492 toggle @Override
1157    public void initInformationWorker(final AlignmentViewPanel ap)
1158    {
1159  492 if (calculator.getWorkersOfClass(InformationThread.class).isEmpty())
1160    {
1161  482 calculator.registerWorker(new InformationThread(this, ap));
1162    }
1163    }
1164    // --------START Structure Conservation
 
1165  1421 toggle public void updateStrucConsensus(final AlignmentViewPanel ap)
1166    {
1167  1421 if (autoCalculateStrucConsensus && strucConsensus == null
1168    && alignment.isNucleotide() && alignment.hasRNAStructure())
1169    {
1170    // secondary structure has been added - so init the consensus line
1171  0 initRNAStructure();
1172    }
1173   
1174    // see note in mantis : issue number 8585
1175  1421 if (strucConsensus == null || !autoCalculateStrucConsensus)
1176    {
1177  1417 return;
1178    }
1179  4 if (calculator.getWorkersOfClass(StrucConsensusThread.class).isEmpty())
1180    {
1181  2 calculator.registerWorker(new StrucConsensusThread(this, ap));
1182    }
1183    }
1184   
 
1185  3579 toggle public boolean isCalcInProgress()
1186    {
1187  3579 return calculator.isWorking();
1188    }
1189   
 
1190  11616 toggle @Override
1191    public boolean isCalculationInProgress(
1192    AlignmentAnnotation alignmentAnnotation)
1193    {
1194  11616 if (!alignmentAnnotation.autoCalculated)
1195    {
1196  0 return false;
1197    }
1198  11616 if (calculator.isWorkingWithAnnotation(alignmentAnnotation))
1199    {
1200    // jalview.bin.Console.errPrintln("grey out
1201    // ("+alignmentAnnotation.label+")");
1202  321 return true;
1203    }
1204  11295 return false;
1205    }
1206   
1207    private ScheduledExecutorService serviceExecutor = Executors.newSingleThreadScheduledExecutor();
1208   
1209    /**
1210    * Get a default scheduled executor service which can be used by
1211    * services and calculators to run parallel jobs associated with this
1212    * viewport.
1213    *
1214    * @return default service executor of that viewport
1215    */
 
1216  26 toggle public ScheduledExecutorService getServiceExecutor()
1217    {
1218  26 return serviceExecutor;
1219    }
1220   
 
1221  907 toggle public void setAlignment(AlignmentI align)
1222    {
1223  907 this.alignment = align;
1224    }
1225   
1226    /**
1227    * Clean up references when this viewport is closed
1228    */
 
1229  312 toggle @Override
1230    public void dispose()
1231    {
1232    /*
1233    * defensively null out references to large objects in case
1234    * this object is not garbage collected (as if!)
1235    */
1236  312 alignPanel=null;
1237  312 consensus = null;
1238  312 complementConsensus = null;
1239  312 strucConsensus = null;
1240  312 secondaryStructureConsensus = null;
1241  312 conservation = null;
1242  312 quality = null;
1243  312 consensusProfiles = null;
1244  312 groupConsensus = null;
1245  312 groupConservation = null;
1246  312 hconsensus = null;
1247  312 hconservation = null;
1248  312 hcomplementConsensus = null;
1249  312 gapcounts = null;
1250  312 calculator.shutdown();
1251  312 calculator = null;
1252  312 serviceExecutor.shutdown();
1253  312 serviceExecutor = null;
1254  312 residueShading = null; // may hold a reference to Consensus
1255  312 changeSupport = null;
1256  312 ranges = null;
1257  312 currentTree = null;
1258  312 selectionGroup = null;
1259  312 colSel = null;
1260  312 setAlignment(null);
1261    }
1262   
 
1263  3813 toggle @Override
1264    public boolean isClosed()
1265    {
1266    // TODO: check that this isClosed is only true after panel is closed, not
1267    // before it is fully constructed.
1268  3813 return alignment == null;
1269    }
1270   
 
1271  3805 toggle @Override
1272    public AlignCalcManagerI2 getCalcManager()
1273    {
1274  3805 return calculator;
1275    }
1276   
1277    /**
1278    * should conservation rows be shown for groups
1279    */
1280    protected boolean showGroupConservation = false;
1281   
1282    /**
1283    * should consensus rows be shown for groups
1284    */
1285    protected boolean showGroupConsensus = false;
1286   
1287    protected boolean showGroupSSConsensus = false;
1288   
1289    /**
1290    * should consensus profile be rendered by default
1291    */
1292    protected boolean showSequenceLogo = false;
1293   
1294    /**
1295    * should consensus profile be rendered normalised to row height
1296    */
1297    protected boolean normaliseSequenceLogo = false;
1298   
1299    /**
1300    * should consensus histograms be rendered by default
1301    */
1302    protected boolean showConsensusHistogram = true;
1303   
1304    /**
1305    * should hmm profile be rendered by default
1306    */
1307    protected boolean hmmShowSequenceLogo = false;
1308   
1309    /**
1310    * should hmm profile be rendered normalised to row height
1311    */
1312    protected boolean hmmNormaliseSequenceLogo = false;
1313   
1314    /**
1315    * should information histograms be rendered by default
1316    */
1317    protected boolean hmmShowHistogram = true;
1318   
1319    /**
1320    * @return the showConsensusProfile
1321    */
 
1322  6600 toggle @Override
1323    public boolean isShowSequenceLogo()
1324    {
1325  6600 return showSequenceLogo;
1326    }
1327   
1328    /**
1329    * @return the showInformationProfile
1330    */
 
1331  1183 toggle @Override
1332    public boolean isShowHMMSequenceLogo()
1333    {
1334  1183 return hmmShowSequenceLogo;
1335    }
1336   
1337    /**
1338    * @param showSequenceLogo
1339    * the new value
1340    */
 
1341  96 toggle public void setShowSequenceLogo(boolean showSequenceLogo)
1342    {
1343  96 if (showSequenceLogo != this.showSequenceLogo)
1344    {
1345    // TODO: decouple settings setting from calculation when refactoring
1346    // annotation update method from alignframe to viewport
1347  20 this.showSequenceLogo = showSequenceLogo;
1348  20 for (AlignCalcWorkerI worker : calculator.getWorkers())
1349    {
1350  80 if (worker.getClass().equals(ConsensusThread.class) ||
1351    worker.getClass().equals(ComplementConsensusThread.class) ||
1352    worker.getClass().equals(StrucConsensusThread.class) ||
1353    worker.getClass().equals(SecondaryStructureConsensusThread.class))
1354    {
1355  40 worker.updateAnnotation();
1356    }
1357    }
1358    }
1359  96 this.showSequenceLogo = showSequenceLogo;
1360    }
1361   
 
1362  595 toggle public void setShowHMMSequenceLogo(boolean showHMMSequenceLogo)
1363    {
1364  595 if (showHMMSequenceLogo != this.hmmShowSequenceLogo)
1365    {
1366  225 this.hmmShowSequenceLogo = showHMMSequenceLogo;
1367    // TODO: updateAnnotation if description (tooltip) will show
1368    // profile in place of information content?
1369    // calculator.updateAnnotationFor(InformationThread.class);
1370    }
1371  595 this.hmmShowSequenceLogo = showHMMSequenceLogo;
1372    }
1373    /**
1374    * @param showConsensusHistogram
1375    * the showConsensusHistogram to set
1376    */
 
1377  96 toggle public void setShowConsensusHistogram(boolean showConsensusHistogram)
1378    {
1379  96 this.showConsensusHistogram = showConsensusHistogram;
1380    }
1381   
1382    /**
1383    * @param showInformationHistogram
1384    */
 
1385  595 toggle public void setShowInformationHistogram(boolean showInformationHistogram)
1386    {
1387  595 this.hmmShowHistogram = showInformationHistogram;
1388    }
1389   
1390    /**
1391    * @return the showGroupConservation
1392    */
 
1393  1219 toggle public boolean isShowGroupConservation()
1394    {
1395  1219 return showGroupConservation;
1396    }
1397   
1398    /**
1399    * @param showGroupConservation
1400    * the showGroupConservation to set
1401    */
 
1402  96 toggle public void setShowGroupConservation(boolean showGroupConservation)
1403    {
1404  96 this.showGroupConservation = showGroupConservation;
1405    }
1406   
1407    /**
1408    * @return the showGroupConsensus
1409    */
 
1410  1219 toggle public boolean isShowGroupConsensus()
1411    {
1412  1219 return showGroupConsensus;
1413    }
1414   
 
1415  1219 toggle public boolean isShowGroupSSConsensus()
1416    {
1417  1219 return showGroupSSConsensus;
1418    }
1419   
1420    /**
1421    * @param showGroupConsensus
1422    * the showGroupConsensus to set
1423    */
 
1424  96 toggle public void setShowGroupConsensus(boolean showGroupConsensus)
1425    {
1426  96 this.showGroupConsensus = showGroupConsensus;
1427    }
1428   
 
1429  96 toggle public void setShowGroupSSConsensus(boolean showGroupSSConsensus)
1430    {
1431  96 this.showGroupSSConsensus = showGroupSSConsensus;
1432    }
1433   
1434    /**
1435    * @param showSSConsensus
1436    * the showSSConsensus to set
1437    */
 
1438  0 toggle public void setShowSSConsensus(boolean showSSConsensus)
1439    {
1440  0 this.showSSConsensus = showSSConsensus;
1441    }
1442   
1443    /**
1444    *
1445    * @return flag to indicate if the consensus histogram should be rendered by
1446    * default
1447    */
 
1448  4421 toggle @Override
1449    public boolean isShowConsensusHistogram()
1450    {
1451  4421 return this.showConsensusHistogram;
1452    }
1453   
1454    /**
1455    *
1456    * @return flag to indicate if the information content histogram should be
1457    * rendered by default
1458    */
 
1459  1183 toggle @Override
1460    public boolean isShowInformationHistogram()
1461    {
1462  1183 return this.hmmShowHistogram;
1463    }
1464   
1465    /**
1466    * when set, updateAlignment will always ensure sequences are of equal length
1467    */
1468    private boolean padGaps = false;
1469   
1470    /**
1471    * when set, alignment should be reordered according to a newly opened tree
1472    */
1473    public boolean sortByTree = false;
1474   
1475    /**
1476    *
1477    *
1478    * @return null or the currently selected sequence region
1479    */
 
1480  29259 toggle @Override
1481    public SequenceGroup getSelectionGroup()
1482    {
1483  29259 return selectionGroup;
1484    }
1485   
1486    /**
1487    * Set the selection group for this window. Also sets the current alignment as
1488    * the context for the group, if it does not already have one.
1489    * @param sg
1490    * - group holding references to sequences in this alignment view
1491    *
1492    */
 
1493  235 toggle @Override
1494    public void setSelectionGroup(SequenceGroup sg)
1495    {
1496  235 selectionGroup = sg;
1497  235 if (sg != null && sg.getContext() == null)
1498    {
1499  37 sg.setContext(alignment);
1500    }
1501    }
1502   
 
1503  1 toggle public void setHiddenColumns(HiddenColumns hidden)
1504    {
1505  1 this.alignment.setHiddenColumns(hidden);
1506    }
1507   
 
1508  5815 toggle @Override
1509    public ColumnSelection getColumnSelection()
1510    {
1511  5815 return colSel;
1512    }
1513   
 
1514  13 toggle @Override
1515    public void setColumnSelection(ColumnSelection colSel)
1516    {
1517  13 this.colSel = colSel;
1518  13 if (colSel != null)
1519    {
1520  13 updateHiddenColumns();
1521    }
1522  13 isColSelChanged(true);
1523    }
1524   
1525    /**
1526    *
1527    * @return
1528    */
 
1529  32 toggle @Override
1530    public Map<SequenceI, SequenceCollectionI> getHiddenRepSequences()
1531    {
1532  32 return hiddenRepSequences;
1533    }
1534   
 
1535  0 toggle @Override
1536    public void setHiddenRepSequences(
1537    Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
1538    {
1539  0 this.hiddenRepSequences = hiddenRepSequences;
1540    }
1541   
 
1542  0 toggle @Override
1543    public boolean hasSelectedColumns()
1544    {
1545  0 ColumnSelection columnSelection = getColumnSelection();
1546  0 return columnSelection != null && columnSelection.hasSelectedColumns();
1547    }
1548   
 
1549  15006 toggle @Override
1550    public boolean hasHiddenColumns()
1551    {
1552  15006 return alignment.getHiddenColumns() != null
1553    && alignment.getHiddenColumns().hasHiddenColumns();
1554    }
1555   
 
1556  14 toggle public void updateHiddenColumns()
1557    {
1558    // this method doesn't really do anything now. But - it could, since a
1559    // column Selection could be in the process of modification
1560    // hasHiddenColumns = colSel.hasHiddenColumns();
1561    }
1562   
 
1563  3747 toggle @Override
1564    public boolean hasHiddenRows()
1565    {
1566  3747 return alignment.getHiddenSequences().getSize() > 0;
1567    }
1568   
1569    protected SequenceGroup selectionGroup;
1570   
 
1571  96 toggle public void setSequenceSetId(String newid)
1572    {
1573  96 if (sequenceSetID != null)
1574    {
1575  96 jalview.bin.Console.errPrintln(
1576    "Warning - overwriting a sequenceSetId for a viewport!");
1577    }
1578  96 sequenceSetID = new String(newid);
1579    }
1580   
 
1581  5279 toggle @Override
1582    public String getSequenceSetId()
1583    {
1584  5279 if (sequenceSetID == null)
1585    {
1586  389 sequenceSetID = alignment.hashCode() + "";
1587    }
1588   
1589  5279 return sequenceSetID;
1590    }
1591   
1592    /**
1593    * unique viewId for synchronizing state (e.g. with stored Jalview Project)
1594    *
1595    */
1596    protected String viewId = null;
1597   
 
1598  615 toggle @Override
1599    public String getViewId()
1600    {
1601  615 if (viewId == null)
1602    {
1603  303 viewId = this.getSequenceSetId() + "." + this.hashCode() + "";
1604    }
1605  615 return viewId;
1606    }
1607   
 
1608  99 toggle public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap)
1609    {
1610  99 ignoreGapsInConsensusCalculation = b;
1611  99 if (ap != null)
1612    {
1613  3 updateConsensus(ap);
1614  3 updateSecondaryStructureConsensus(ap);
1615  3 if (residueShading != null)
1616    {
1617  3 residueShading.setThreshold(residueShading.getThreshold(),
1618    ignoreGapsInConsensusCalculation);
1619    }
1620    }
1621    }
1622   
 
1623  0 toggle public void setIgnoreBelowBackground(boolean b, AlignmentViewPanel ap)
1624    {
1625  0 ignoreBelowBackGroundFrequencyCalculation = b;
1626    }
1627   
 
1628  0 toggle public void setInfoLetterHeight(boolean b, AlignmentViewPanel ap)
1629    {
1630  0 infoLetterHeight = b;
1631    }
1632   
1633    private long sgrouphash = -1, colselhash = -1;
1634   
1635    /**
1636    * checks current SelectionGroup against record of last hash value, and
1637    * updates record.
1638    *
1639    * @param b
1640    * update the record of last hash value
1641    *
1642    * @return true if SelectionGroup changed since last call (when b is true)
1643    */
 
1644  443 toggle public boolean isSelectionGroupChanged(boolean b)
1645    {
1646  443 int hc = (selectionGroup == null || selectionGroup.getSize() == 0) ? -1
1647    : selectionGroup.hashCode();
1648  443 if (hc != -1 && hc != sgrouphash)
1649    {
1650  105 if (b)
1651    {
1652  9 sgrouphash = hc;
1653    }
1654  105 return true;
1655    }
1656  338 return false;
1657    }
1658   
1659    /**
1660    * checks current colsel against record of last hash value, and optionally
1661    * updates record.
1662    *
1663    * @param updateHash
1664    * update the record of last hash value
1665    * @return true if colsel changed since last call (when b is true)
1666    */
 
1667  266 toggle public boolean isColSelChanged(boolean updateHash)
1668    {
1669  266 int hc = (colSel == null || colSel.isEmpty()) ? -1 : colSel.hashCode();
1670  266 if (hc != -1 && hc != colselhash)
1671    {
1672  17 if (updateHash)
1673    {
1674  17 colselhash = hc;
1675    }
1676  17 return true;
1677    }
1678  249 notifySequence();
1679  249 return false;
1680    }
1681   
 
1682  5455 toggle @Override
1683    public boolean isIgnoreGapsConsensus()
1684    {
1685  5455 return ignoreGapsInConsensusCalculation;
1686    }
1687   
 
1688  3205 toggle @Override
1689    public boolean isIgnoreBelowBackground()
1690    {
1691  3205 return ignoreBelowBackGroundFrequencyCalculation;
1692    }
1693   
 
1694  3205 toggle @Override
1695    public boolean isInfoLetterHeight()
1696    {
1697  3205 return infoLetterHeight;
1698    }
1699    // property change stuff
1700    // JBPNote Prolly only need this in the applet version.
1701    private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
1702    this);
1703   
1704    protected boolean showConservation = true;
1705   
1706    protected boolean showQuality = true;
1707   
1708    protected boolean showConsensus = true;
1709   
1710    protected boolean showSSConsensus = true;
1711   
1712    protected boolean showOccupancy = true;
1713   
1714    private Map<SequenceI, Color> sequenceColours = new HashMap<>();
1715   
1716    private Map<AlignmentAnnotation, Color> annotationColours = new HashMap<>();
1717   
1718    protected SequenceAnnotationOrder sortAnnotationsBy = null;
1719   
1720    protected boolean showAutocalculatedAbove;
1721   
1722    /**
1723    * when set, view will scroll to show the highlighted position
1724    */
1725    private boolean followHighlight = true;
1726   
1727    /**
1728    * Property change listener for changes in alignment
1729    *
1730    * @param listener
1731    * DOCUMENT ME!
1732    */
 
1733  529 toggle public void addPropertyChangeListener(
1734    java.beans.PropertyChangeListener listener)
1735    {
1736  529 changeSupport.addPropertyChangeListener(listener);
1737    }
1738   
1739    /**
1740    * DOCUMENT ME!
1741    *
1742    * @param listener
1743    * DOCUMENT ME!
1744    */
 
1745  331 toggle public void removePropertyChangeListener(
1746    java.beans.PropertyChangeListener listener)
1747    {
1748  331 if (changeSupport != null)
1749    {
1750  330 changeSupport.removePropertyChangeListener(listener);
1751    }
1752    }
1753   
1754    /**
1755    * Property change listener for changes in alignment
1756    *
1757    * @param prop
1758    * DOCUMENT ME!
1759    * @param oldvalue
1760    * DOCUMENT ME!
1761    * @param newvalue
1762    * DOCUMENT ME!
1763    */
 
1764  0 toggle public void firePropertyChange(String prop, Object oldvalue,
1765    Object newvalue)
1766    {
1767  0 changeSupport.firePropertyChange(prop, oldvalue, newvalue);
1768    }
1769   
1770   
1771    /**
1772    * Notify TreePanel and AlignmentPanel of some sort of alignment change.
1773    */
 
1774  75 toggle public void notifyAlignment()
1775    {
1776  75 changeSupport.firePropertyChange(PROPERTY_ALIGNMENT, null, alignment.getSequences());
1777    }
1778   
1779    /**
1780    * Notify AlignmentPanel of a sequence column selection or visibility changes.
1781    */
 
1782  250 toggle public void notifySequence()
1783    {
1784  250 changeSupport.firePropertyChange(PROPERTY_SEQUENCE, null, null);
1785    }
1786   
 
1787  0 toggle @Override
1788    public void notifyAlignmentChanged()
1789    {
1790  0 firePropertyChange("alignment", null, alignment);
1791    }
1792   
1793    // common hide/show column stuff
1794   
 
1795  6 toggle public void hideSelectedColumns()
1796    {
1797  6 if (colSel.isEmpty())
1798    {
1799  2 return;
1800    }
1801   
1802  4 colSel.hideSelectedColumns(alignment);
1803  4 setSelectionGroup(null);
1804  4 isColSelChanged(true);
1805    }
1806   
 
1807  71 toggle public void hideColumns(int start, int end)
1808    {
1809  71 if (start == end)
1810    {
1811  2 colSel.hideSelectedColumns(start, alignment.getHiddenColumns());
1812    }
1813    else
1814    {
1815  69 alignment.getHiddenColumns().hideColumns(start, end);
1816    }
1817  71 isColSelChanged(true);
1818    }
1819   
 
1820  1 toggle public void showColumn(int col)
1821    {
1822  1 alignment.getHiddenColumns().revealHiddenColumns(col, colSel);
1823  1 isColSelChanged(true);
1824    }
1825   
 
1826  5 toggle public void showAllHiddenColumns()
1827    {
1828  5 alignment.getHiddenColumns().revealAllHiddenColumns(colSel);
1829  5 isColSelChanged(true);
1830    }
1831   
1832    // common hide/show seq stuff
 
1833  1 toggle public void showAllHiddenSeqs()
1834    {
1835  1 int startSeq = ranges.getStartSeq();
1836  1 int endSeq = ranges.getEndSeq();
1837   
1838  1 if (alignment.getHiddenSequences().getSize() > 0)
1839    {
1840  1 if (selectionGroup == null)
1841    {
1842  0 selectionGroup = new SequenceGroup();
1843  0 selectionGroup.setEndRes(alignment.getWidth() - 1);
1844    }
1845  1 List<SequenceI> tmp = alignment.getHiddenSequences()
1846    .showAll(hiddenRepSequences);
1847  1 for (SequenceI seq : tmp)
1848    {
1849  2 selectionGroup.addSequence(seq, false);
1850  2 setSequenceAnnotationsVisible(seq, true);
1851    }
1852   
1853  1 hiddenRepSequences = null;
1854   
1855  1 ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
1856   
1857    // used to set hasHiddenRows/hiddenRepSequences here, after the property
1858    // changed event
1859  1 notifySequence();
1860  1 sendSelection();
1861    }
1862    }
1863   
 
1864  2 toggle public void showSequence(int index)
1865    {
1866  2 int startSeq = ranges.getStartSeq();
1867  2 int endSeq = ranges.getEndSeq();
1868   
1869  2 List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(index,
1870    hiddenRepSequences);
1871  2 if (tmp.size() > 0)
1872    {
1873  2 if (selectionGroup == null)
1874    {
1875  2 selectionGroup = new SequenceGroup();
1876  2 selectionGroup.setEndRes(alignment.getWidth() - 1);
1877    }
1878   
1879  2 for (SequenceI seq : tmp)
1880    {
1881  3 selectionGroup.addSequence(seq, false);
1882  3 setSequenceAnnotationsVisible(seq, true);
1883    }
1884   
1885  2 ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
1886   
1887  2 notifyAlignment();
1888  2 sendSelection();
1889    }
1890    }
1891   
 
1892  0 toggle public void hideAllSelectedSeqs()
1893    {
1894  0 if (selectionGroup == null || selectionGroup.getSize() < 1)
1895    {
1896  0 return;
1897    }
1898   
1899  0 SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);
1900   
1901  0 hideSequence(seqs);
1902   
1903  0 setSelectionGroup(null);
1904    }
1905   
 
1906  54 toggle public void hideSequence(SequenceI[] seq)
1907    {
1908    /*
1909    * cache offset to first visible sequence
1910    */
1911  54 int startSeq = ranges.getStartSeq();
1912   
1913  54 if (seq != null)
1914    {
1915  252 for (int i = 0; i < seq.length; i++)
1916    {
1917  198 alignment.getHiddenSequences().hideSequence(seq[i]);
1918  198 setSequenceAnnotationsVisible(seq[i], false);
1919    }
1920  54 ranges.setStartSeq(startSeq);
1921  54 notifyAlignment();
1922    }
1923    }
1924   
1925    /**
1926    * Hides the specified sequence, or the sequences it represents
1927    *
1928    * @param sequence
1929    * the sequence to hide, or keep as representative
1930    * @param representGroup
1931    * if true, hide the current selection group except for the
1932    * representative sequence
1933    */
 
1934  3 toggle public void hideSequences(SequenceI sequence, boolean representGroup)
1935    {
1936  3 if (selectionGroup == null || selectionGroup.getSize() < 1)
1937    {
1938  0 hideSequence(new SequenceI[] { sequence });
1939  0 return;
1940    }
1941   
1942  3 if (representGroup)
1943    {
1944  3 hideRepSequences(sequence, selectionGroup);
1945  3 setSelectionGroup(null);
1946  3 return;
1947    }
1948   
1949  0 int gsize = selectionGroup.getSize();
1950  0 SequenceI[] hseqs = selectionGroup.getSequences()
1951    .toArray(new SequenceI[gsize]);
1952   
1953  0 hideSequence(hseqs);
1954  0 setSelectionGroup(null);
1955  0 sendSelection();
1956    }
1957   
1958    /**
1959    * Set visibility for any annotations for the given sequence.
1960    *
1961    * @param sequenceI
1962    */
 
1963  203 toggle protected void setSequenceAnnotationsVisible(SequenceI sequenceI,
1964    boolean visible)
1965    {
1966  203 AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
1967  203 if (anns != null)
1968    {
1969  203 for (AlignmentAnnotation ann : anns)
1970    {
1971  1033 if (ann.sequenceRef == sequenceI)
1972    {
1973  0 ann.visible = visible;
1974    }
1975    }
1976    }
1977    }
1978   
 
1979  5 toggle public void hideRepSequences(SequenceI repSequence, SequenceGroup sg)
1980    {
1981  5 int sSize = sg.getSize();
1982  5 if (sSize < 2)
1983    {
1984  0 return;
1985    }
1986   
1987  5 if (hiddenRepSequences == null)
1988    {
1989  5 hiddenRepSequences = new Hashtable<>();
1990    }
1991   
1992  5 hiddenRepSequences.put(repSequence, sg);
1993   
1994    // Hide all sequences except the repSequence
1995  5 SequenceI[] seqs = new SequenceI[sSize - 1];
1996  5 int index = 0;
1997  16 for (int i = 0; i < sSize; i++)
1998    {
1999  11 if (sg.getSequenceAt(i) != repSequence)
2000    {
2001  6 if (index == sSize - 1)
2002    {
2003  0 return;
2004    }
2005   
2006  6 seqs[index++] = sg.getSequenceAt(i);
2007    }
2008    }
2009  5 sg.setSeqrep(repSequence); // note: not done in 2.7applet
2010  5 sg.setHidereps(true); // note: not done in 2.7applet
2011  5 hideSequence(seqs);
2012   
2013    }
2014   
2015    /**
2016    *
2017    * @return null or the current reference sequence
2018    */
 
2019  0 toggle public SequenceI getReferenceSeq()
2020    {
2021  0 return alignment.getSeqrep();
2022    }
2023   
2024    /**
2025    * @param seq
2026    * @return true iff seq is the reference for the alignment
2027    */
 
2028  411 toggle public boolean isReferenceSeq(SequenceI seq)
2029    {
2030  411 return alignment.getSeqrep() == seq;
2031    }
2032   
2033    /**
2034    *
2035    * @param seq
2036    * @return true if there are sequences represented by this sequence that are
2037    * currently hidden
2038    */
 
2039  598 toggle public boolean isHiddenRepSequence(SequenceI seq)
2040    {
2041  598 return (hiddenRepSequences != null
2042    && hiddenRepSequences.containsKey(seq));
2043    }
2044   
2045    /**
2046    *
2047    * @param seq
2048    * @return null or a sequence group containing the sequences that seq
2049    * represents
2050    */
 
2051  2 toggle public SequenceGroup getRepresentedSequences(SequenceI seq)
2052    {
2053  2 return (SequenceGroup) (hiddenRepSequences == null ? null
2054    : hiddenRepSequences.get(seq));
2055    }
2056   
 
2057  0 toggle @Override
2058    public int adjustForHiddenSeqs(int alignmentIndex)
2059    {
2060  0 return alignment.getHiddenSequences()
2061    .adjustForHiddenSeqs(alignmentIndex);
2062    }
2063   
 
2064  0 toggle @Override
2065    public void invertColumnSelection()
2066    {
2067  0 colSel.invertColumnSelection(0, alignment.getWidth(), alignment);
2068  0 isColSelChanged(true);
2069    }
2070   
 
2071  4 toggle @Override
2072    public SequenceI[] getSelectionAsNewSequence()
2073    {
2074  4 SequenceI[] sequences;
2075    // JBPNote: Need to test jalviewLite.getSelectedSequencesAsAlignmentFrom -
2076    // this was the only caller in the applet for this method
2077    // JBPNote: in applet, this method returned references to the alignment
2078    // sequences, and it did not honour the presence/absence of annotation
2079    // attached to the alignment (probably!)
2080  4 if (selectionGroup == null || selectionGroup.getSize() == 0)
2081    {
2082  2 sequences = alignment.getSequencesArray();
2083  2 AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation();
2084  4 for (int i = 0; i < sequences.length; i++)
2085    {
2086    // construct new sequence with subset of visible annotation
2087  2 sequences[i] = new Sequence(sequences[i], annots);
2088    }
2089    }
2090    else
2091    {
2092  2 sequences = selectionGroup.getSelectionAsNewSequences(alignment);
2093    }
2094   
2095  4 return sequences;
2096    }
2097   
 
2098  28 toggle @Override
2099    public SequenceI[] getSequenceSelection()
2100    {
2101  28 SequenceI[] sequences = null;
2102  28 if (selectionGroup != null)
2103    {
2104  4 sequences = selectionGroup.getSequencesInOrder(alignment);
2105    }
2106  28 if (sequences == null)
2107    {
2108  24 sequences = alignment.getSequencesArray();
2109    }
2110  28 return sequences;
2111    }
2112   
 
2113  73 toggle @Override
2114    public jalview.datamodel.AlignmentView getAlignmentView(
2115    boolean selectedOnly)
2116    {
2117  73 return getAlignmentView(selectedOnly, false);
2118    }
2119   
 
2120  74 toggle @Override
2121    public jalview.datamodel.AlignmentView getAlignmentView(
2122    boolean selectedOnly, boolean markGroups)
2123    {
2124  74 return new AlignmentView(alignment, alignment.getHiddenColumns(),
2125    selectionGroup,
2126    alignment.getHiddenColumns() != null
2127    && alignment.getHiddenColumns().hasHiddenColumns(),
2128    selectedOnly, markGroups);
2129    }
2130   
 
2131  24 toggle @Override
2132    public String[] getViewAsString(boolean selectedRegionOnly)
2133    {
2134  24 return getViewAsString(selectedRegionOnly, true);
2135    }
2136   
 
2137  24 toggle @Override
2138    public String[] getViewAsString(boolean selectedRegionOnly,
2139    boolean exportHiddenSeqs)
2140    {
2141  24 String[] selection = null;
2142  24 SequenceI[] seqs = null;
2143  24 int i, iSize;
2144  24 int start = 0, end = 0;
2145  24 if (selectedRegionOnly && selectionGroup != null)
2146    {
2147  0 iSize = selectionGroup.getSize();
2148  0 seqs = selectionGroup.getSequencesInOrder(alignment);
2149  0 start = selectionGroup.getStartRes();
2150  0 end = selectionGroup.getEndRes() + 1;
2151    }
2152    else
2153    {
2154  24 if (hasHiddenRows() && exportHiddenSeqs)
2155    {
2156  0 AlignmentI fullAlignment = alignment.getHiddenSequences()
2157    .getFullAlignment();
2158  0 iSize = fullAlignment.getHeight();
2159  0 seqs = fullAlignment.getSequencesArray();
2160  0 end = fullAlignment.getWidth();
2161    }
2162    else
2163    {
2164  24 iSize = alignment.getHeight();
2165  24 seqs = alignment.getSequencesArray();
2166  24 end = alignment.getWidth();
2167    }
2168    }
2169   
2170  24 selection = new String[iSize];
2171  24 if (alignment.getHiddenColumns() != null
2172    && alignment.getHiddenColumns().hasHiddenColumns())
2173    {
2174  206 for (i = 0; i < iSize; i++)
2175    {
2176  188 Iterator<int[]> blocks = alignment.getHiddenColumns()
2177    .getVisContigsIterator(start, end + 1, false);
2178  188 selection[i] = seqs[i].getSequenceStringFromIterator(blocks);
2179    }
2180    }
2181    else
2182    {
2183  36 for (i = 0; i < iSize; i++)
2184    {
2185  30 selection[i] = seqs[i].getSequenceAsString(start, end);
2186    }
2187   
2188    }
2189  24 return selection;
2190    }
2191   
 
2192  0 toggle @Override
2193    public List<int[]> getVisibleRegionBoundaries(int min, int max)
2194    {
2195  0 ArrayList<int[]> regions = new ArrayList<>();
2196  0 int start = min;
2197  0 int end = max;
2198   
2199  0 do
2200    {
2201  0 HiddenColumns hidden = alignment.getHiddenColumns();
2202  0 if (hidden != null && hidden.hasHiddenColumns())
2203    {
2204  0 if (start == 0)
2205    {
2206  0 start = hidden.visibleToAbsoluteColumn(start);
2207    }
2208   
2209  0 end = hidden.getNextHiddenBoundary(false, start);
2210  0 if (start == end)
2211    {
2212  0 end = max;
2213    }
2214  0 if (end > max)
2215    {
2216  0 end = max;
2217    }
2218    }
2219   
2220  0 regions.add(new int[] { start, end });
2221   
2222  0 if (hidden != null && hidden.hasHiddenColumns())
2223    {
2224  0 start = hidden.visibleToAbsoluteColumn(end);
2225  0 start = hidden.getNextHiddenBoundary(true, start) + 1;
2226    }
2227  0 } while (end < max);
2228   
2229    // int[][] startEnd = new int[regions.size()][2];
2230   
2231  0 return regions;
2232    }
2233   
 
2234  1 toggle @Override
2235    public List<AlignmentAnnotation> getVisibleAlignmentAnnotation(
2236    boolean selectedOnly)
2237    {
2238  1 ArrayList<AlignmentAnnotation> ala = new ArrayList<>();
2239  1 AlignmentAnnotation[] aa;
2240  ? if ((aa = alignment.getAlignmentAnnotation()) != null)
2241    {
2242  1 for (AlignmentAnnotation annot : aa)
2243    {
2244  4 AlignmentAnnotation clone = new AlignmentAnnotation(annot);
2245  4 if (selectedOnly && selectionGroup != null)
2246    {
2247  4 clone.makeVisibleAnnotation(
2248    selectionGroup.getStartRes(), selectionGroup.getEndRes(),
2249    alignment.getHiddenColumns());
2250    }
2251    else
2252    {
2253  0 clone.makeVisibleAnnotation(alignment.getHiddenColumns());
2254    }
2255  4 ala.add(clone);
2256    }
2257    }
2258  1 return ala;
2259    }
2260   
 
2261  2150 toggle @Override
2262    public boolean isPadGaps()
2263    {
2264  2150 return padGaps;
2265    }
2266   
 
2267  595 toggle @Override
2268    public void setPadGaps(boolean padGaps)
2269    {
2270  595 this.padGaps = padGaps;
2271    }
2272   
2273    /**
2274    * apply any post-edit constraints and trigger any calculations needed after
2275    * an edit has been performed on the alignment
2276    *
2277    * @param ap
2278    */
 
2279  929 toggle @Override
2280    public void alignmentChanged(AlignmentViewPanel ap)
2281    {
2282  929 if (isPadGaps())
2283    {
2284  470 alignment.padGaps();
2285    }
2286  929 if (autoCalculateConsensusAndConservation)
2287    {
2288  929 updateConsensus(ap);
2289  929 updateSecondaryStructureConsensus(ap);
2290    }
2291  929 if (hconsensus != null && autoCalculateConsensusAndConservation)
2292    {
2293  573 updateConservation(ap);
2294    }
2295  929 if (autoCalculateStrucConsensus)
2296    {
2297  929 updateStrucConsensus(ap);
2298    }
2299   
2300    // Reset endRes of groups if beyond alignment width
2301  929 int alWidth = alignment.getWidth();
2302  929 List<SequenceGroup> groups = alignment.getGroups();
2303  929 if (groups != null)
2304    {
2305  929 for (SequenceGroup sg : groups)
2306    {
2307  237 if (sg.getEndRes() > alWidth)
2308    {
2309  0 sg.setEndRes(alWidth - 1);
2310    }
2311    }
2312    }
2313   
2314  929 if (selectionGroup != null && selectionGroup.getEndRes() > alWidth)
2315    {
2316  0 selectionGroup.setEndRes(alWidth - 1);
2317    }
2318   
2319  929 updateAllColourSchemes();
2320  929 calculator.restartWorkers();
2321    }
2322   
2323    /**
2324    * reset scope and do calculations for all applied colourschemes on alignment
2325    */
 
2326  929 toggle void updateAllColourSchemes()
2327    {
2328  929 ResidueShaderI rs = residueShading;
2329  929 if (rs != null)
2330    {
2331  929 rs.alignmentChanged(alignment, hiddenRepSequences);
2332   
2333  929 rs.setConsensus(hconsensus);
2334  929 if (rs.conservationApplied())
2335    {
2336  3 rs.setConservation(Conservation.calculateConservation("All",
2337    alignment.getSequences(), 0, alignment.getWidth(), false,
2338    getConsPercGaps(), false));
2339    }
2340    }
2341   
2342  929 for (SequenceGroup sg : alignment.getGroups())
2343    {
2344  237 if (sg.cs != null)
2345    {
2346  237 sg.cs.alignmentChanged(sg, hiddenRepSequences);
2347    }
2348  237 sg.recalcConservation();
2349    }
2350    }
2351   
 
2352  595 toggle protected void initAutoAnnotation()
2353    {
2354    // TODO: add menu option action that nulls or creates consensus object
2355    // depending on if the user wants to see the annotation or not in a
2356    // specific alignment
2357   
2358  595 if (hconsensus == null && !isDataset)
2359    {
2360  595 if (!alignment.isNucleotide())
2361    {
2362  475 initConservation();
2363  475 initQuality();
2364    }
2365    else
2366    {
2367  120 initRNAStructure();
2368    }
2369  595 consensus = new AlignmentAnnotation("Consensus",
2370    MessageManager.getString("label.consensus_descr"),
2371    new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
2372  595 setSecondaryStructureSources(alignment.getAlignmentAnnotation());
2373   
2374  595 List<String> secondaryStructureSources = getSecondaryStructureSources();
2375  595 boolean singleProvider = false;
2376   
2377  595 if (secondaryStructureSources != null)
2378    {
2379  595 if(secondaryStructureSources.size() == 2)
2380    {
2381  16 singleProvider = true; //Single provider if size is 2 (All, Provider 1)
2382    }
2383   
2384  595 AlignmentUtils.assignColorsForSecondaryStructureProviders(secondaryStructureSources);
2385   
2386  595 secondaryStructureConsensus = new ArrayList<AlignmentAnnotation>();
2387  595 for (String ssSource : secondaryStructureSources)
2388    {
2389   
2390  526 AlignmentAnnotation ssConsensus = new AlignmentAnnotation(
2391    MessageManager.getString("label.ssconsensus_label") + " "
2392    + ssSource,
2393    ssSource + " "
2394    + MessageManager
2395    .getString("label.ssconsensus_descr"),
2396    new Annotation[1], 0f, 100f,
2397    AlignmentAnnotation.BAR_GRAPH);
2398  526 ssConsensus.autoCalculated=true;
2399  526 ssConsensus.hasData=false;
2400  526 ssConsensus.hasText=true;
2401    // Hide global ss consensus for all providers if only one provider is present
2402  526 ssConsensus.visible = ssSource.equals(Constants.SS_ALL_PROVIDERS) && singleProvider ? false : true;
2403   
2404  526 secondaryStructureConsensus.add(ssConsensus);
2405    }
2406   
2407    }
2408   
2409  595 initConsensus(consensus);
2410  595 initSSConsensus(secondaryStructureConsensus);
2411  595 initGapCounts();
2412  595 initComplementConsensus();
2413    }
2414    }
2415    /**
2416    * set Secondary structure annotation providers for current set of annotation
2417    */
 
2418  3046 toggle @Override
2419    public void setSecondaryStructureSources()
2420    {
2421  3046 List<String> sources = null;
2422  3046 AlignmentAnnotation[] aa = getAlignment()
2423    .getAlignmentAnnotation();
2424  3046 if (aa != null)
2425    {
2426  3046 sources = AlignmentUtils.extractSSSourceInAlignmentAnnotation(aa);
2427  3046 if (sources != null)
2428    {
2429  3046 sources.add(0, Constants.SS_ALL_PROVIDERS);
2430  3046 setSecondaryStructureSources(sources);
2431    }
2432    }
2433    }
2434   
2435    /**
2436    * If this is a protein alignment and there are mappings to cDNA, adds the
2437    * cDNA consensus annotation and returns true, else returns false.
2438    */
 
2439  605 toggle public boolean initComplementConsensus()
2440    {
2441  605 if (!alignment.isNucleotide())
2442    {
2443  484 final List<AlignedCodonFrame> codonMappings = alignment
2444    .getCodonFrames();
2445  484 if (codonMappings != null && !codonMappings.isEmpty())
2446    {
2447  4 boolean doConsensus = false;
2448  4 for (AlignedCodonFrame mapping : codonMappings)
2449    {
2450    // TODO hold mapping type e.g. dna-to-protein in AlignedCodonFrame?
2451  4 MapList[] mapLists = mapping.getdnaToProt();
2452    // mapLists can be empty if project load has not finished resolving
2453    // seqs
2454  4 if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
2455    {
2456  4 doConsensus = true;
2457  4 break;
2458    }
2459    }
2460  4 if (doConsensus)
2461    {
2462  4 Iterable<AlignmentAnnotation> annots = alignment
2463    .findAnnotations(null, null, "cDNA Consensus");
2464  4 if (annots != null && (complementConsensus == null))
2465    {
2466  4 for (AlignmentAnnotation ann : annots)
2467    {
2468  0 if (ann.autoCalculated)
2469    {
2470  0 complementConsensus = ann;
2471    }
2472    }
2473    }
2474  4 if (complementConsensus == null)
2475    {
2476  4 complementConsensus = new AlignmentAnnotation("cDNA Consensus",
2477    MessageManager
2478    .getString("label.complement_consensus_descr"),
2479    new Annotation[1], 0f, 100f,
2480    AlignmentAnnotation.BAR_GRAPH);
2481  4 initConsensus(complementConsensus);
2482    }
2483  4 return true;
2484    }
2485    }
2486    }
2487  601 return false;
2488    }
2489   
 
2490  599 toggle private void initConsensus(AlignmentAnnotation aa)
2491    {
2492  599 aa.hasText = true;
2493  599 aa.autoCalculated = true;
2494   
2495  599 if (showConsensus)
2496    {
2497  598 alignment.addAnnotation(aa);
2498    }
2499    }
2500   
 
2501  595 toggle private void initSSConsensus(
2502    List<AlignmentAnnotation> secondaryStructureConsensuses)
2503    {
2504  595 if (secondaryStructureConsensuses == null)
2505    {
2506  0 return;
2507    }
2508  595 for (AlignmentAnnotation aa : secondaryStructureConsensuses)
2509    {
2510  526 aa.hasText = true;
2511  526 aa.autoCalculated = true;
2512   
2513  526 if (showSSConsensus)
2514    {
2515  0 alignment.addAnnotation(aa);
2516    }
2517   
2518    }
2519    }
2520   
2521    // these should be extracted from the view model - style and settings for
2522    // derived annotation
 
2523  595 toggle private void initGapCounts()
2524    {
2525  595 if (showOccupancy)
2526    {
2527  591 gapcounts = new AlignmentAnnotation("Occupancy",
2528    MessageManager.getString("label.occupancy_descr"),
2529    new Annotation[1], 0f, alignment.getHeight(),
2530    AlignmentAnnotation.BAR_GRAPH);
2531  591 gapcounts.hasText = true;
2532  591 gapcounts.autoCalculated = true;
2533  591 gapcounts.scaleColLabel = true;
2534  591 gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
2535   
2536  591 alignment.addAnnotation(gapcounts);
2537    }
2538    }
2539   
 
2540  475 toggle private void initConservation()
2541    {
2542  475 if (showConservation)
2543    {
2544  474 if (conservation == null)
2545    {
2546  474 conservation = new AlignmentAnnotation("Conservation",
2547    MessageManager.formatMessage("label.conservation_descr",
2548    getConsPercGaps()),
2549    new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
2550  474 conservation.hasText = true;
2551  474 conservation.autoCalculated = true;
2552  474 alignment.addAnnotation(conservation);
2553    }
2554    }
2555    }
2556   
 
2557  475 toggle private void initQuality()
2558    {
2559  475 if (showQuality)
2560    {
2561  475 if (quality == null)
2562    {
2563  475 quality = new AlignmentAnnotation("Quality",
2564    MessageManager.getString("label.quality_descr"),
2565    new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
2566  475 quality.hasText = true;
2567  475 quality.autoCalculated = true;
2568  475 alignment.addAnnotation(quality);
2569    }
2570    }
2571    }
2572   
 
2573  120 toggle private void initRNAStructure()
2574    {
2575  120 if (alignment.hasRNAStructure() && strucConsensus == null)
2576    {
2577  2 strucConsensus = new AlignmentAnnotation("StrucConsensus",
2578    MessageManager.getString("label.strucconsensus_descr"),
2579    new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
2580  2 strucConsensus.hasText = true;
2581  2 strucConsensus.autoCalculated = true;
2582   
2583  2 if (showConsensus)
2584    {
2585  2 alignment.addAnnotation(strucConsensus);
2586    }
2587    }
2588    }
2589   
2590    /*
2591    * (non-Javadoc)
2592    *
2593    * @see jalview.api.AlignViewportI#calcPanelHeight()
2594    */
 
2595  6921 toggle @Override
2596    public int calcPanelHeight()
2597    {
2598    // setHeight of panels
2599  6921 AlignmentAnnotation[] anns = getAlignment().getAlignmentAnnotation();
2600  6921 int height = 0;
2601  6921 int charHeight = getCharHeight();
2602  6921 if (anns != null)
2603    {
2604  6921 BitSet graphgrp = new BitSet();
2605  6921 for (AlignmentAnnotation aa : anns)
2606    {
2607  35276 if (aa == null)
2608    {
2609  0 jalview.bin.Console.errPrintln("Null annotation row: ignoring.");
2610  0 continue;
2611    }
2612  35276 if (!aa.isForDisplay())
2613    {
2614  5514 continue;
2615    }
2616  29762 if (aa.graphGroup > -1)
2617    {
2618  300 if (graphgrp.get(aa.graphGroup))
2619    {
2620  15 continue;
2621    }
2622    else
2623    {
2624  285 graphgrp.set(aa.graphGroup);
2625    }
2626    }
2627  29747 aa.height = 0;
2628   
2629  29747 if (aa.hasText)
2630    {
2631  26176 aa.height += charHeight;
2632    }
2633   
2634  29747 if (aa.hasIcons)
2635    {
2636  2246 aa.height += 16;
2637    }
2638   
2639  29747 if (aa.graph > 0)
2640    {
2641  26339 aa.height += aa.graphHeight + 20;
2642    }
2643   
2644  29747 if (aa.height == 0)
2645    {
2646  432 aa.height = 20;
2647    }
2648   
2649  29747 height += aa.height;
2650    }
2651    }
2652  6921 if (height == 0)
2653    {
2654    // set minimum
2655  28 height = 20;
2656    }
2657  6921 return height;
2658    }
2659   
 
2660  440 toggle @Override
2661    public void updateGroupAnnotationSettings(boolean applyGlobalSettings,
2662    boolean preserveNewGroupSettings)
2663    {
2664  440 boolean updateCalcs = false;
2665  440 boolean conv = isShowGroupConservation();
2666  440 boolean cons = isShowGroupConsensus();
2667  440 boolean sscons = isShowGroupSSConsensus();
2668  440 boolean showprf = isShowSequenceLogo();
2669  440 boolean showConsHist = isShowConsensusHistogram();
2670  440 boolean normLogo = isNormaliseSequenceLogo();
2671  440 boolean showHMMPrf = isShowHMMSequenceLogo();
2672  440 boolean showInfoHist = isShowInformationHistogram();
2673  440 boolean normHMMLogo = isNormaliseHMMSequenceLogo();
2674   
2675    /**
2676    * TODO reorder the annotation rows according to group/sequence ordering on
2677    * alignment
2678    */
2679    // boolean sortg = true;
2680   
2681    // remove old automatic annotation
2682    // add any new annotation
2683   
2684    // intersect alignment annotation with alignment groups
2685   
2686  440 AlignmentAnnotation[] aan = alignment.getAlignmentAnnotation();
2687   
2688  440 List<SequenceGroup> oldrfs = new ArrayList<>();
2689  440 if (aan != null)
2690    {
2691  2847 for (int an = 0; an < aan.length; an++)
2692    {
2693  2407 if (aan[an].autoCalculated && aan[an].groupRef != null)
2694    {
2695  0 oldrfs.add(aan[an].groupRef);
2696  0 alignment.deleteAnnotation(aan[an], false);
2697    }
2698    }
2699    }
2700  440 if (alignment.getGroups() != null)
2701    {
2702  440 for (SequenceGroup sg : alignment.getGroups())
2703    {
2704  70 updateCalcs = false;
2705  70 if (applyGlobalSettings
2706    || (!preserveNewGroupSettings && !oldrfs.contains(sg)))
2707    {
2708    // set defaults for this group's conservation/consensus
2709  11 sg.setshowSequenceLogo(showprf);
2710  11 sg.setShowConsensusHistogram(showConsHist);
2711  11 sg.setNormaliseSequenceLogo(normLogo);
2712  11 sg.setShowHMMSequenceLogo(showHMMPrf);
2713  11 sg.setShowInformationHistogram(showInfoHist);
2714  11 sg.setNormaliseHMMSequenceLogo(normHMMLogo);
2715    }
2716  70 if (conv)
2717    {
2718  0 updateCalcs = true;
2719  0 alignment.addAnnotation(sg.getConservationRow(), 0);
2720    }
2721  70 if (cons)
2722    {
2723  24 updateCalcs = true;
2724  24 alignment.addAnnotation(sg.getConsensus(), 0);
2725    }
2726  70 if (sscons)
2727    {
2728  0 updateCalcs = true;
2729  0 List<String> secondaryStructureSources = getSecondaryStructureSources();
2730  0 if (secondaryStructureSources != null)
2731    {
2732  0 List<AlignmentAnnotation> ssAa = sg
2733    .getSSConsensus(secondaryStructureSources);
2734  0 if (ssAa != null)
2735    {
2736  0 for (AlignmentAnnotation aa : ssAa)
2737    {
2738    // Setting annotation visibility to true for the secondary
2739    // structure consensus for all providers
2740  0 if (aa.label.contains(Constants.SS_ALL_PROVIDERS))
2741    {
2742  0 aa.visible = true;
2743    }
2744  0 alignment.addAnnotation(aa, 0);
2745    }
2746    }
2747    }
2748    }
2749    // refresh the annotation rows
2750  70 if (updateCalcs)
2751    {
2752  24 sg.recalcConservation();
2753    }
2754    }
2755    }
2756  440 oldrfs.clear();
2757    }
2758   
 
2759  26657 toggle @Override
2760    public boolean isDisplayReferenceSeq()
2761    {
2762  26657 return alignment.hasSeqrep() && viewStyle.isDisplayReferenceSeq();
2763    }
2764   
 
2765  10 toggle @Override
2766    public void setDisplayReferenceSeq(boolean displayReferenceSeq)
2767    {
2768  10 viewStyle.setDisplayReferenceSeq(displayReferenceSeq);
2769    }
2770   
 
2771  5 toggle @Override
2772    public boolean isColourByReferenceSeq()
2773    {
2774  5 return alignment.hasSeqrep() && viewStyle.isColourByReferenceSeq();
2775    }
2776   
 
2777  30051 toggle @Override
2778    public Color getSequenceColour(SequenceI seq)
2779    {
2780  30051 Color sqc = sequenceColours.get(seq);
2781  30051 return (sqc == null ? Color.white : sqc);
2782    }
2783   
 
2784  1325 toggle @Override
2785    public void setSequenceColour(SequenceI seq, Color col)
2786    {
2787  1325 if (col == null)
2788    {
2789  0 sequenceColours.remove(seq);
2790    }
2791    else
2792    {
2793  1325 sequenceColours.put(seq, col);
2794    }
2795    }
2796   
 
2797  9 toggle @Override
2798    public void updateSequenceIdColours()
2799    {
2800  9 for (SequenceGroup sg : alignment.getGroups())
2801    {
2802  5 if (sg.idColour != null)
2803    {
2804  0 for (SequenceI s : sg.getSequences(getHiddenRepSequences()))
2805    {
2806  0 sequenceColours.put(s, sg.idColour);
2807    }
2808    }
2809    }
2810    }
2811   
 
2812  1 toggle @Override
2813    public void clearSequenceColours()
2814    {
2815  1 sequenceColours.clear();
2816    }
2817   
2818   
 
2819  188 toggle @Override
2820    public Color getAnnotationColour(AlignmentAnnotation annot)
2821    {
2822  188 Color annotColor = annotationColours.get(annot);
2823  188 return (annotColor == null ? Color.white : annotColor);
2824    }
2825   
 
2826  12 toggle @Override
2827    public void setAnnotationColour(AlignmentAnnotation annot, Color col)
2828    {
2829  12 if (col == null)
2830    {
2831  0 annotationColours.remove(annot);
2832  0 annot.setAnnotationGroupColour(Color.WHITE);
2833    }
2834    else
2835    {
2836  12 annotationColours.put(annot, col);
2837  12 annot.setAnnotationGroupColour(col);
2838    }
2839    }
2840   
 
2841  1283 toggle @Override
2842    public void updateAnnotationColours()
2843    {
2844  1283 for (SequenceGroup sg : alignment.getGroups())
2845    {
2846  930 if (sg.idColour != null)
2847    {
2848  925 for (AlignmentAnnotation annot : sg.getAlignmentAnnotation())
2849    {
2850  384 annotationColours.put(annot, sg.idColour);
2851  384 annot.setAnnotationGroupColour(sg.idColour);
2852    }
2853    }
2854    }
2855    }
2856   
 
2857  1 toggle @Override
2858    public void clearAnnotationColours()
2859    {
2860  1 for (AlignmentAnnotation annot : annotationColours.keySet())
2861    {
2862  4 annot.setAnnotationGroupColour(Color.WHITE);
2863    }
2864  1 annotationColours.clear();
2865    }
2866   
 
2867  0 toggle @Override
2868    public Map<AlignmentAnnotation, Color> getAnnotationColours()
2869    {
2870  0 return annotationColours;
2871    }
2872   
 
2873  0 toggle @Override
2874    public void setAnnotationColours(
2875    Map<AlignmentAnnotation, Color> annotationColours)
2876    {
2877  0 this.annotationColours = annotationColours;
2878    }
2879   
 
2880  1273 toggle @Override
2881    public AlignViewportI getCodingComplement()
2882    {
2883  1273 return this.codingComplement;
2884    }
2885   
2886    /**
2887    * Set this as the (cDna/protein) complement of the given viewport. Also
2888    * ensures the reverse relationship is set on the given viewport.
2889    */
 
2890  6 toggle @Override
2891    public void setCodingComplement(AlignViewportI av)
2892    {
2893  6 if (this == av)
2894    {
2895  0 jalview.bin.Console
2896    .errPrintln("Ignoring recursive setCodingComplement request");
2897    }
2898    else
2899    {
2900  6 this.codingComplement = av;
2901    // avoid infinite recursion!
2902  6 if (av.getCodingComplement() != this)
2903    {
2904  3 av.setCodingComplement(this);
2905    }
2906    }
2907    }
2908   
 
2909  25 toggle @Override
2910    public boolean isNucleotide()
2911    {
2912  25 return getAlignment() == null ? false : getAlignment().isNucleotide();
2913    }
2914   
 
2915  1142962 toggle @Override
2916    public FeaturesDisplayedI getFeaturesDisplayed()
2917    {
2918  1142962 return featuresDisplayed;
2919    }
2920   
 
2921  119 toggle @Override
2922    public void setFeaturesDisplayed(FeaturesDisplayedI featuresDisplayedI)
2923    {
2924  119 featuresDisplayed = featuresDisplayedI;
2925    }
2926   
 
2927  83 toggle @Override
2928    public boolean areFeaturesDisplayed()
2929    {
2930  83 return featuresDisplayed != null
2931    && featuresDisplayed.getRegisteredFeaturesCount() > 0;
2932    }
2933   
2934    /**
2935    * set the flag
2936    *
2937    * @param b
2938    * features are displayed if true
2939    */
 
2940  156 toggle @Override
2941    public void setShowSequenceFeatures(boolean b)
2942    {
2943  156 viewStyle.setShowSequenceFeatures(b);
2944    }
2945   
 
2946  419456 toggle @Override
2947    public boolean isShowSequenceFeatures()
2948    {
2949  419464 return viewStyle.isShowSequenceFeatures();
2950    }
2951   
 
2952  0 toggle @Override
2953    public void setShowSequenceFeaturesHeight(boolean selected)
2954    {
2955  0 viewStyle.setShowSequenceFeaturesHeight(selected);
2956    }
2957   
 
2958  0 toggle @Override
2959    public boolean isShowSequenceFeaturesHeight()
2960    {
2961  0 return viewStyle.isShowSequenceFeaturesHeight();
2962    }
2963   
 
2964  799 toggle @Override
2965    public void setShowAnnotation(boolean b)
2966    {
2967  799 viewStyle.setShowAnnotation(b);
2968    }
2969   
 
2970  5540 toggle @Override
2971    public boolean isShowAnnotation()
2972    {
2973  5540 return viewStyle.isShowAnnotation();
2974    }
2975   
 
2976  16305 toggle @Override
2977    public boolean isRightAlignIds()
2978    {
2979  16305 return viewStyle.isRightAlignIds();
2980    }
2981   
 
2982  691 toggle @Override
2983    public void setRightAlignIds(boolean rightAlignIds)
2984    {
2985  691 viewStyle.setRightAlignIds(rightAlignIds);
2986    }
2987   
 
2988  1115 toggle @Override
2989    public boolean getConservationSelected()
2990    {
2991  1115 return viewStyle.getConservationSelected();
2992    }
2993   
 
2994  96 toggle @Override
2995    public void setShowBoxes(boolean state)
2996    {
2997  96 viewStyle.setShowBoxes(state);
2998    }
2999   
3000    /**
3001    * @return
3002    * @see jalview.api.ViewStyleI#getTextColour()
3003    */
 
3004  834786 toggle @Override
3005    public Color getTextColour()
3006    {
3007  834787 return viewStyle.getTextColour();
3008    }
3009   
3010    /**
3011    * @return
3012    * @see jalview.api.ViewStyleI#getTextColour2()
3013    */
 
3014  50 toggle @Override
3015    public Color getTextColour2()
3016    {
3017  50 return viewStyle.getTextColour2();
3018    }
3019   
3020    /**
3021    * @return
3022    * @see jalview.api.ViewStyleI#getThresholdTextColour()
3023    */
 
3024  789451 toggle @Override
3025    public int getThresholdTextColour()
3026    {
3027  789452 return viewStyle.getThresholdTextColour();
3028    }
3029   
3030    /**
3031    * @return
3032    * @see jalview.api.ViewStyleI#isConservationColourSelected()
3033    */
 
3034  0 toggle @Override
3035    public boolean isConservationColourSelected()
3036    {
3037  0 return viewStyle.isConservationColourSelected();
3038    }
3039   
3040    /**
3041    * @return
3042    * @see jalview.api.ViewStyleI#isRenderGaps()
3043    */
 
3044  5949 toggle @Override
3045    public boolean isRenderGaps()
3046    {
3047  5949 return viewStyle.isRenderGaps();
3048    }
3049   
3050    /**
3051    * @return
3052    * @see jalview.api.ViewStyleI#isShowColourText()
3053    */
 
3054  729 toggle @Override
3055    public boolean isShowColourText()
3056    {
3057  729 return viewStyle.isShowColourText();
3058    }
3059   
3060    /**
3061    * @param conservationColourSelected
3062    * @see jalview.api.ViewStyleI#setConservationColourSelected(boolean)
3063    */
 
3064  0 toggle @Override
3065    public void setConservationColourSelected(
3066    boolean conservationColourSelected)
3067    {
3068  0 viewStyle.setConservationColourSelected(conservationColourSelected);
3069    }
3070   
3071    /**
3072    * @param showColourText
3073    * @see jalview.api.ViewStyleI#setShowColourText(boolean)
3074    */
 
3075  0 toggle @Override
3076    public void setShowColourText(boolean showColourText)
3077    {
3078  0 viewStyle.setShowColourText(showColourText);
3079    }
3080   
3081    /**
3082    * @param textColour
3083    * @see jalview.api.ViewStyleI#setTextColour(java.awt.Color)
3084    */
 
3085  96 toggle @Override
3086    public void setTextColour(Color textColour)
3087    {
3088  96 viewStyle.setTextColour(textColour);
3089    }
3090   
3091    /**
3092    * @param thresholdTextColour
3093    * @see jalview.api.ViewStyleI#setThresholdTextColour(int)
3094    */
 
3095  96 toggle @Override
3096    public void setThresholdTextColour(int thresholdTextColour)
3097    {
3098  96 viewStyle.setThresholdTextColour(thresholdTextColour);
3099    }
3100   
3101    /**
3102    * @param textColour2
3103    * @see jalview.api.ViewStyleI#setTextColour2(java.awt.Color)
3104    */
 
3105  96 toggle @Override
3106    public void setTextColour2(Color textColour2)
3107    {
3108  96 viewStyle.setTextColour2(textColour2);
3109    }
3110   
 
3111  158 toggle @Override
3112    public ViewStyleI getViewStyle()
3113    {
3114  158 return new ViewStyle(viewStyle);
3115    }
3116   
 
3117  97 toggle @Override
3118    public void setViewStyle(ViewStyleI settingsForView)
3119    {
3120  97 viewStyle = new ViewStyle(settingsForView);
3121  97 if (residueShading != null)
3122    {
3123  97 residueShading.setConservationApplied(
3124    settingsForView.isConservationColourSelected());
3125    }
3126    }
3127   
 
3128  0 toggle @Override
3129    public boolean sameStyle(ViewStyleI them)
3130    {
3131  0 return viewStyle.sameStyle(them);
3132    }
3133   
3134    /**
3135    * @return
3136    * @see jalview.api.ViewStyleI#getIdWidth()
3137    */
 
3138  8821 toggle @Override
3139    public int getIdWidth()
3140    {
3141  8821 return viewStyle.getIdWidth();
3142    }
3143   
3144    /**
3145    * @param i
3146    * @see jalview.api.ViewStyleI#setIdWidth(int)
3147    */
 
3148  737 toggle @Override
3149    public void setIdWidth(int i)
3150    {
3151  737 viewStyle.setIdWidth(i);
3152    }
3153   
3154    /**
3155    * @return
3156    * @see jalview.api.ViewStyleI#isCentreColumnLabels()
3157    */
 
3158  729 toggle @Override
3159    public boolean isCentreColumnLabels()
3160    {
3161  729 return viewStyle.isCentreColumnLabels();
3162    }
3163   
3164    /**
3165    * @param centreColumnLabels
3166    * @see jalview.api.ViewStyleI#setCentreColumnLabels(boolean)
3167    */
 
3168  691 toggle @Override
3169    public void setCentreColumnLabels(boolean centreColumnLabels)
3170    {
3171  691 viewStyle.setCentreColumnLabels(centreColumnLabels);
3172    }
3173   
3174    /**
3175    * @param showdbrefs
3176    * @see jalview.api.ViewStyleI#setShowDBRefs(boolean)
3177    */
 
3178  691 toggle @Override
3179    public void setShowDBRefs(boolean showdbrefs)
3180    {
3181  691 viewStyle.setShowDBRefs(showdbrefs);
3182    }
3183   
3184    /**
3185    * @return
3186    * @see jalview.api.ViewStyleI#isShowDBRefs()
3187    */
 
3188  779 toggle @Override
3189    public boolean isShowDBRefs()
3190    {
3191  779 return viewStyle.isShowDBRefs();
3192    }
3193   
3194    /**
3195    * @return
3196    * @see jalview.api.ViewStyleI#isShowNPFeats()
3197    */
 
3198  779 toggle @Override
3199    public boolean isShowNPFeats()
3200    {
3201  779 return viewStyle.isShowNPFeats();
3202    }
3203   
3204    /**
3205    * @param shownpfeats
3206    * @see jalview.api.ViewStyleI#setShowNPFeats(boolean)
3207    */
 
3208  691 toggle @Override
3209    public void setShowNPFeats(boolean shownpfeats)
3210    {
3211  691 viewStyle.setShowNPFeats(shownpfeats);
3212    }
3213   
3214    public abstract StructureSelectionManager getStructureSelectionManager();
3215   
3216    /**
3217    * Add one command to the command history list.
3218    *
3219    * @param command
3220    */
 
3221  1 toggle public void addToHistoryList(CommandI command)
3222    {
3223  1 if (this.historyList != null)
3224    {
3225  1 this.historyList.push(command);
3226  1 broadcastCommand(command, false);
3227  1 setSavedUpToDate(false);
3228  1 Jalview2XML.setStateSavedUpToDate(false);
3229    }
3230    }
3231   
 
3232  1 toggle protected void broadcastCommand(CommandI command, boolean undo)
3233    {
3234  1 getStructureSelectionManager().commandPerformed(command, undo,
3235    getVamsasSource());
3236    }
3237   
3238    /**
3239    * Add one command to the command redo list.
3240    *
3241    * @param command
3242    */
 
3243  0 toggle public void addToRedoList(CommandI command)
3244    {
3245  0 if (this.redoList != null)
3246    {
3247  0 this.redoList.push(command);
3248    }
3249  0 broadcastCommand(command, true);
3250    }
3251   
3252    /**
3253    * Clear the command redo list.
3254    */
 
3255  1 toggle public void clearRedoList()
3256    {
3257  1 if (this.redoList != null)
3258    {
3259  1 this.redoList.clear();
3260    }
3261    }
3262   
 
3263  53 toggle public void setHistoryList(Deque<CommandI> list)
3264    {
3265  53 this.historyList = list;
3266    }
3267   
 
3268  1705 toggle public Deque<CommandI> getHistoryList()
3269    {
3270  1705 return this.historyList;
3271    }
3272   
 
3273  53 toggle public void setRedoList(Deque<CommandI> list)
3274    {
3275  53 this.redoList = list;
3276    }
3277   
 
3278  1703 toggle public Deque<CommandI> getRedoList()
3279    {
3280  1703 return this.redoList;
3281    }
3282   
 
3283  1 toggle @Override
3284    public VamsasSource getVamsasSource()
3285    {
3286  1 return this;
3287    }
3288   
 
3289  7209 toggle public SequenceAnnotationOrder getSortAnnotationsBy()
3290    {
3291  7209 return sortAnnotationsBy;
3292    }
3293   
 
3294  0 toggle public void setSortAnnotationsBy(
3295    SequenceAnnotationOrder sortAnnotationsBy)
3296    {
3297  0 this.sortAnnotationsBy = sortAnnotationsBy;
3298    }
3299   
 
3300  7209 toggle public boolean isShowAutocalculatedAbove()
3301    {
3302  7209 return showAutocalculatedAbove;
3303    }
3304   
 
3305  487 toggle public void setShowAutocalculatedAbove(boolean showAutocalculatedAbove)
3306    {
3307  487 this.showAutocalculatedAbove = showAutocalculatedAbove;
3308    }
3309   
 
3310  3 toggle @Override
3311    public boolean isScaleProteinAsCdna()
3312    {
3313  3 return viewStyle.isScaleProteinAsCdna();
3314    }
3315   
 
3316  0 toggle @Override
3317    public void setScaleProteinAsCdna(boolean b)
3318    {
3319  0 viewStyle.setScaleProteinAsCdna(b);
3320    }
3321   
 
3322  0 toggle @Override
3323    public boolean isProteinFontAsCdna()
3324    {
3325  0 return viewStyle.isProteinFontAsCdna();
3326    }
3327   
 
3328  0 toggle @Override
3329    public void setProteinFontAsCdna(boolean b)
3330    {
3331  0 viewStyle.setProteinFontAsCdna(b);
3332    }
3333   
 
3334  96 toggle @Override
3335    public void setShowComplementFeatures(boolean b)
3336    {
3337  96 viewStyle.setShowComplementFeatures(b);
3338    }
3339   
 
3340  416968 toggle @Override
3341    public boolean isShowComplementFeatures()
3342    {
3343  416996 return viewStyle.isShowComplementFeatures();
3344    }
3345   
 
3346  96 toggle @Override
3347    public void setShowComplementFeaturesOnTop(boolean b)
3348    {
3349  96 viewStyle.setShowComplementFeaturesOnTop(b);
3350    }
3351   
 
3352  51 toggle @Override
3353    public boolean isShowComplementFeaturesOnTop()
3354    {
3355  51 return viewStyle.isShowComplementFeaturesOnTop();
3356    }
3357   
3358    /**
3359    * @return true if view should scroll to show the highlighted region of a
3360    * sequence
3361    * @return
3362    */
 
3363  60 toggle @Override
3364    public final boolean isFollowHighlight()
3365    {
3366  60 return followHighlight;
3367    }
3368   
 
3369  96 toggle @Override
3370    public final void setFollowHighlight(boolean b)
3371    {
3372  96 this.followHighlight = b;
3373    }
3374   
 
3375  51999 toggle @Override
3376    public ViewportRanges getRanges()
3377    {
3378  51999 return ranges;
3379    }
3380   
3381    /**
3382    * Helper method to populate the SearchResults with the location in the
3383    * complementary alignment to scroll to, in order to match this one.
3384    *
3385    * @param sr
3386    * the SearchResults to add to
3387    * @return the offset (below top of visible region) of the matched sequence
3388    */
 
3389  654 toggle protected int findComplementScrollTarget(SearchResultsI sr)
3390    {
3391  654 final AlignViewportI complement = getCodingComplement();
3392  654 if (complement == null || !complement.isFollowHighlight())
3393    {
3394  652 return 0;
3395    }
3396  2 boolean iAmProtein = !getAlignment().isNucleotide();
3397  2 AlignmentI proteinAlignment = iAmProtein ? getAlignment()
3398    : complement.getAlignment();
3399  2 if (proteinAlignment == null)
3400    {
3401  0 return 0;
3402    }
3403  2 final List<AlignedCodonFrame> mappings = proteinAlignment
3404    .getCodonFrames();
3405   
3406    /*
3407    * Heuristic: find the first mapped sequence (if any) with a non-gapped
3408    * residue in the middle column of the visible region. Scroll the
3409    * complementary alignment to line up the corresponding residue.
3410    */
3411  2 int seqOffset = 0;
3412  2 SequenceI sequence = null;
3413   
3414    /*
3415    * locate 'middle' column (true middle if an odd number visible, left of
3416    * middle if an even number visible)
3417    */
3418  2 int middleColumn = ranges.getStartRes()
3419    + (ranges.getEndRes() - ranges.getStartRes()) / 2;
3420  2 final HiddenSequences hiddenSequences = getAlignment()
3421    .getHiddenSequences();
3422   
3423    /*
3424    * searching to the bottom of the alignment gives smoother scrolling across
3425    * all gapped visible regions
3426    */
3427  2 int lastSeq = alignment.getHeight() - 1;
3428  2 List<AlignedCodonFrame> seqMappings = null;
3429  2 for (int seqNo = ranges
3430  2 .getStartSeq(); seqNo <= lastSeq; seqNo++, seqOffset++)
3431    {
3432  2 sequence = getAlignment().getSequenceAt(seqNo);
3433  2 if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
3434    {
3435  0 continue;
3436    }
3437  2 if (Comparison.isGap(sequence.getCharAt(middleColumn)))
3438    {
3439  0 continue;
3440    }
3441  2 seqMappings = MappingUtils.findMappingsForSequenceAndOthers(sequence,
3442    mappings,
3443    getCodingComplement().getAlignment().getSequences());
3444  2 if (!seqMappings.isEmpty())
3445    {
3446  2 break;
3447    }
3448    }
3449   
3450  2 if (sequence == null || seqMappings == null || seqMappings.isEmpty())
3451    {
3452    /*
3453    * No ungapped mapped sequence in middle column - do nothing
3454    */
3455  0 return 0;
3456    }
3457  2 MappingUtils.addSearchResults(sr, sequence,
3458    sequence.findPosition(middleColumn), seqMappings);
3459  2 return seqOffset;
3460    }
3461   
3462    /**
3463    * synthesize a column selection if none exists so it covers the given
3464    * selection group. if wholewidth is false, no column selection is made if the
3465    * selection group covers the whole alignment width.
3466    *
3467    * @param sg
3468    * @param wholewidth
3469    */
 
3470  0 toggle public void expandColSelection(SequenceGroup sg, boolean wholewidth)
3471    {
3472  0 int sgs, sge;
3473  0 if (sg != null && (sgs = sg.getStartRes()) >= 0
3474    && sg.getStartRes() <= (sge = sg.getEndRes())
3475    && !this.hasSelectedColumns())
3476    {
3477  0 if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
3478    {
3479    // do nothing
3480  0 return;
3481    }
3482  0 if (colSel == null)
3483    {
3484  0 colSel = new ColumnSelection();
3485    }
3486  0 for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
3487    {
3488  0 colSel.addElement(cspos);
3489    }
3490    }
3491    }
3492   
3493    /**
3494    * hold status of current selection group - defined on alignment or not.
3495    */
3496    private boolean selectionIsDefinedGroup = false;
3497   
 
3498  0 toggle @Override
3499    public boolean isSelectionDefinedGroup()
3500    {
3501  0 if (selectionGroup == null)
3502    {
3503  0 return false;
3504    }
3505  0 if (isSelectionGroupChanged(true))
3506    {
3507  0 selectionIsDefinedGroup = false;
3508  0 List<SequenceGroup> gps = alignment.getGroups();
3509  0 if (gps == null || gps.size() == 0)
3510    {
3511  0 selectionIsDefinedGroup = false;
3512    }
3513    else
3514    {
3515  0 selectionIsDefinedGroup = gps.contains(selectionGroup);
3516    }
3517    }
3518  0 return selectionGroup.isDefined() || selectionIsDefinedGroup;
3519    }
3520   
3521    /**
3522    * null, or currently highlighted results on this view
3523    */
3524    private SearchResultsI searchResults = null;
3525   
3526    protected TreeModel currentTree = null;
3527   
 
3528  13113 toggle @Override
3529    public boolean hasSearchResults()
3530    {
3531  13113 return searchResults != null;
3532    }
3533   
 
3534  14 toggle @Override
3535    public void setSearchResults(SearchResultsI results)
3536    {
3537  14 searchResults = results;
3538    }
3539   
 
3540  102 toggle @Override
3541    public SearchResultsI getSearchResults()
3542    {
3543  102 return searchResults;
3544    }
3545   
 
3546  6029 toggle @Override
3547    public ContactListI getContactList(AlignmentAnnotation _aa, int column)
3548    {
3549  6029 return alignment.getContactListFor(_aa, column);
3550    }
3551   
 
3552  386 toggle @Override
3553    public ContactMatrixI getContactMatrix(
3554    AlignmentAnnotation alignmentAnnotation)
3555    {
3556  386 return alignment.getContactMatrixFor(alignmentAnnotation);
3557    }
3558   
3559    /**
3560    * get the consensus sequence as displayed under the PID consensus annotation
3561    * row.
3562    *
3563    * @return consensus sequence as a new sequence object
3564    */
 
3565  1 toggle public SequenceI getConsensusSeq()
3566    {
3567  1 if (consensus == null)
3568    {
3569  0 updateConsensus(null);
3570    }
3571  1 if (consensus == null)
3572    {
3573  0 return null;
3574    }
3575  1 StringBuffer seqs = new StringBuffer();
3576  4 for (int i = 0; i < consensus.annotations.length; i++)
3577    {
3578  3 Annotation annotation = consensus.annotations[i];
3579  3 if (annotation != null)
3580    {
3581  3 String description = annotation.description;
3582  3 if (description != null && description.startsWith("["))
3583    {
3584    // consensus is a tie - just pick the first one
3585  1 seqs.append(description.charAt(1));
3586    }
3587    else
3588    {
3589  2 seqs.append(annotation.displayCharacter);
3590    }
3591    }
3592    }
3593   
3594  1 SequenceI sq = new Sequence("Consensus", seqs.toString());
3595  1 sq.setDescription("Percentage Identity Consensus "
3596  1 + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
3597  1 return sq;
3598    }
3599   
3600    // TODO JAL-4386
 
3601  0 toggle public SequenceI getSSConsensusSeq()
3602    {
3603  0 if (secondaryStructureConsensus == null)
3604    {
3605  0 updateSecondaryStructureConsensus(null);
3606    }
3607  0 if (secondaryStructureConsensus == null)
3608    {
3609  0 return null;
3610    }
3611  0 StringBuffer seqs = new StringBuffer();
3612    // for (int i = 0; i < secondaryStructureConsensus.annotations.length; i++)
3613    // {
3614    // Annotation annotation = secondaryStructureConsensus.annotations[i];
3615    // if (annotation != null)
3616    // {
3617    // String description = annotation.description;
3618    // if (description != null && description.startsWith("["))
3619    // {
3620    // // consensus is a tie - just pick the first one
3621    // seqs.append(description.charAt(1));
3622    // }
3623    // else
3624    // {
3625    // seqs.append(annotation.displayCharacter);
3626    // }
3627    // }
3628    // }
3629   
3630  0 SequenceI sq = new Sequence("Sec Str Consensus", seqs.toString());
3631  0 sq.setDescription("Percentage Identity Sec Str Consensus "
3632  0 + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
3633  0 return sq;
3634    }
3635   
 
3636  0 toggle public boolean hasReferenceAnnotation()
3637    {
3638  0 AlignmentAnnotation[] annots = this.alignment.getAlignmentAnnotation();
3639  0 for (AlignmentAnnotation annot : annots)
3640    {
3641  0 if ("RF".equals(annot.label) || annot.label.contains("Reference"))
3642    {
3643  0 return true;
3644    }
3645    }
3646  0 return false;
3647    }
 
3648  22 toggle @Override
3649    public void setCurrentTree(TreeModel tree)
3650    {
3651  22 currentTree = tree;
3652    }
3653   
 
3654  71 toggle @Override
3655    public TreeModel getCurrentTree()
3656    {
3657  71 return currentTree;
3658    }
3659   
 
3660  121 toggle @Override
3661    public AlignmentExportData getAlignExportData(AlignExportSettingsI options)
3662    {
3663  121 AlignmentI alignmentToExport = null;
3664  121 String[] omitHidden = null;
3665  121 alignmentToExport = null;
3666   
3667  121 if (hasHiddenColumns() && !options.isExportHiddenColumns())
3668    {
3669  0 omitHidden = getViewAsString(false,
3670    options.isExportHiddenSequences());
3671    }
3672   
3673  121 int[] alignmentStartEnd = new int[2];
3674  121 if (hasHiddenRows() && options.isExportHiddenSequences())
3675    {
3676  0 alignmentToExport = getAlignment().getHiddenSequences()
3677    .getFullAlignment();
3678    }
3679    else
3680    {
3681  121 alignmentToExport = getAlignment();
3682    }
3683  121 alignmentStartEnd = getAlignment().getHiddenColumns()
3684    .getVisibleStartAndEndIndex(alignmentToExport.getWidth());
3685  121 AlignmentExportData ed = new AlignmentExportData(alignmentToExport,
3686    omitHidden, alignmentStartEnd);
3687  121 return ed;
3688    }
3689   
 
3690  0 toggle @Override
3691    public boolean isNormaliseSequenceLogo()
3692    {
3693  0 return normaliseSequenceLogo;
3694    }
3695   
 
3696  0 toggle public void setNormaliseSequenceLogo(boolean state)
3697    {
3698  0 normaliseSequenceLogo = state;
3699    }
3700   
 
3701  1183 toggle @Override
3702    public boolean isNormaliseHMMSequenceLogo()
3703    {
3704  1183 return hmmNormaliseSequenceLogo;
3705    }
3706   
 
3707  595 toggle public void setNormaliseHMMSequenceLogo(boolean state)
3708    {
3709  595 hmmNormaliseSequenceLogo = state;
3710    }
3711    /**
3712    * flag set to indicate if structure views might be out of sync with sequences
3713    * in the alignment
3714    */
3715   
3716    private boolean needToUpdateStructureViews = false;
3717   
 
3718  0 toggle @Override
3719    public boolean isUpdateStructures()
3720    {
3721  0 return needToUpdateStructureViews;
3722    }
3723   
 
3724  3 toggle @Override
3725    public void setUpdateStructures(boolean update)
3726    {
3727  3 needToUpdateStructureViews = update;
3728    }
3729   
 
3730  4142 toggle @Override
3731    public boolean needToUpdateStructureViews()
3732    {
3733  4142 boolean update = needToUpdateStructureViews;
3734  4142 needToUpdateStructureViews = false;
3735  4142 return update;
3736    }
3737   
 
3738  2 toggle @Override
3739    public void addSequenceGroup(SequenceGroup sequenceGroup)
3740    {
3741  2 alignment.addGroup(sequenceGroup);
3742   
3743  2 Color col = sequenceGroup.idColour;
3744  2 if (col != null)
3745    {
3746  2 col = col.brighter();
3747   
3748  2 for (SequenceI sq : sequenceGroup.getSequences())
3749    {
3750  15 setSequenceColour(sq, col);
3751    }
3752   
3753  2 List<AlignmentAnnotation> annotations = sequenceGroup.getAnnotationsFromTree();
3754  2 if (annotations != null) {
3755  2 for (AlignmentAnnotation annot : annotations) {
3756  4 setAnnotationColour(annot, col);
3757    }
3758    }
3759    }
3760   
3761  2 if (codingComplement != null)
3762    {
3763  0 SequenceGroup mappedGroup = MappingUtils
3764    .mapSequenceGroup(sequenceGroup, this, codingComplement);
3765  0 if (mappedGroup.getSequences().size() > 0)
3766    {
3767  0 codingComplement.getAlignment().addGroup(mappedGroup);
3768   
3769  0 if (col != null)
3770    {
3771  0 for (SequenceI seq : mappedGroup.getSequences())
3772    {
3773  0 codingComplement.setSequenceColour(seq, col);
3774    }
3775    }
3776    }
3777    // propagate the structure view update flag according to our own setting
3778  0 codingComplement.setUpdateStructures(needToUpdateStructureViews);
3779    }
3780    }
3781   
 
3782  34 toggle @Override
3783    public Iterator<int[]> getViewAsVisibleContigs(boolean selectedRegionOnly)
3784    {
3785  34 int start = 0;
3786  34 int end = 0;
3787  34 if (selectedRegionOnly && selectionGroup != null)
3788    {
3789  4 start = selectionGroup.getStartRes();
3790  4 end = selectionGroup.getEndRes() + 1;
3791    }
3792    else
3793    {
3794  30 end = alignment.getWidth();
3795    }
3796  34 return (alignment.getHiddenColumns().getVisContigsIterator(start, end,
3797    false));
3798    }
3799   
 
3800  133 toggle public void setSavedUpToDate(boolean s)
3801    {
3802  133 setSavedUpToDate(s, QuitHandler.Message.UNSAVED_CHANGES);
3803    }
3804   
 
3805  465 toggle public void setSavedUpToDate(boolean s, QuitHandler.Message m)
3806    {
3807  465 Console.debug(
3808    "Setting " + this.getViewId() + " setSavedUpToDate to " + s);
3809  465 savedUpToDate = s;
3810  465 QuitHandler.setMessage(m);
3811    }
3812   
 
3813  4 toggle public boolean savedUpToDate()
3814    {
3815  4 Console.debug("Returning " + this.getViewId() + " savedUpToDate value: "
3816    + savedUpToDate);
3817  4 return savedUpToDate;
3818    }
3819    /**
3820    * Filters out sequences with an eValue higher than the specified value. The
3821    * filtered sequences are hidden or deleted. Sequences with no eValues are also
3822    * filtered out.
3823    *
3824    * @param eValue
3825    * @param delete
3826    */
 
3827  0 toggle public void filterByEvalue(double eValue)
3828    {
3829  0 for (SequenceI seq : alignment.getSequencesArray())
3830    {
3831  0 if ((seq.getAnnotation("Search Scores") == null
3832    || seq.getAnnotation("Search Scores")[0].getEValue() > eValue)
3833    && seq.getHMM() == null)
3834    {
3835  0 hideSequence(new SequenceI[] { seq });
3836    }
3837    }
3838    }
3839   
3840    /**
3841    * Filters out sequences with an score lower than the specified value. The
3842    * filtered sequences are hidden or deleted.
3843    *
3844    * @param score
3845    * @param delete
3846    */
 
3847  0 toggle public void filterByScore(double score)
3848    {
3849  0 for (SequenceI seq : alignment.getSequencesArray())
3850    {
3851  0 if ((seq.getAnnotation("Search Scores") == null
3852    || seq.getAnnotation("Search Scores")[0]
3853    .getBitScore() < score)
3854    && seq.getHMM() == null)
3855    {
3856  0 hideSequence(new SequenceI[] { seq });
3857    }
3858    }
3859    }
3860    }