X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fviewmodel%2FAlignmentViewport.java;h=a15e9a67b0300ebf547796632e7d68df93fb93bc;hb=17e77c3f2949a0729322b4a8d907f3f34b6a9914;hp=cb97ea8bad7cfc682c7317b52e3dd34b73559c55;hpb=648f0d7f48b5865bd43b5edbe71f5e483f0cc455;p=jalview.git diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index cb97ea8..a15e9a6 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -1,6 +1,6 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) - * Copyright (C) 2014 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9) + * Copyright (C) 2015 The Jalview Authors * * This file is part of Jalview. * @@ -20,16 +20,23 @@ */ package jalview.viewmodel; +import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; import jalview.analysis.Conservation; import jalview.api.AlignCalcManagerI; import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; import jalview.api.FeaturesDisplayedI; +import jalview.api.ViewStyleI; +import jalview.commands.CommandI; +import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentView; import jalview.datamodel.Annotation; +import jalview.datamodel.CigarArray; import jalview.datamodel.ColumnSelection; +import jalview.datamodel.HiddenSequences; +import jalview.datamodel.SearchResults; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceGroup; @@ -38,18 +45,27 @@ import jalview.schemes.Blosum62ColourScheme; import jalview.schemes.ColourSchemeI; import jalview.schemes.PIDColourScheme; import jalview.schemes.ResidueProperties; -import jalview.viewmodel.seqfeatures.FeaturesDisplayed; +import jalview.structure.CommandListener; +import jalview.structure.StructureSelectionManager; +import jalview.structure.VamsasSource; +import jalview.util.Comparison; +import jalview.util.MappingUtils; +import jalview.viewmodel.styles.ViewStyle; import jalview.workers.AlignCalcManager; +import jalview.workers.ComplementConsensusThread; import jalview.workers.ConsensusThread; import jalview.workers.StrucConsensusThread; import java.awt.Color; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.BitSet; +import java.util.Deque; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; -import java.util.Vector; +import java.util.Set; /** * base class holding visualization and analysis attributes and common logic for @@ -58,1617 +74,2487 @@ import java.util.Vector; * @author jimp * */ -public abstract class AlignmentViewport implements AlignViewportI +public abstract class AlignmentViewport implements AlignViewportI, + CommandListener, VamsasSource { - /** - * alignment displayed in the viewport. Please use get/setter - */ - protected AlignmentI alignment; - - protected String sequenceSetID; + protected ViewStyleI viewStyle = new ViewStyle(); /** - * probably unused indicator that view is of a dataset rather than an - * alignment + * A viewport that hosts the cDna view of this (protein), or vice versa (if + * set). */ - protected boolean isDataset = false; + AlignViewportI codingComplement = null; - private Map hiddenRepSequences; + FeaturesDisplayedI featuresDisplayed = null; - protected ColumnSelection colSel = new ColumnSelection(); + protected Deque historyList = new ArrayDeque(); - public boolean autoCalculateConsensus = true; + protected Deque redoList = new ArrayDeque(); - protected boolean autoCalculateStrucConsensus = true; + /** + * @param name + * @see jalview.api.ViewStyleI#setFontName(java.lang.String) + */ + public void setFontName(String name) + { + viewStyle.setFontName(name); + } - protected boolean ignoreGapsInConsensusCalculation = false; + /** + * @param style + * @see jalview.api.ViewStyleI#setFontStyle(int) + */ + public void setFontStyle(int style) + { + viewStyle.setFontStyle(style); + } - protected ColourSchemeI globalColourScheme = null; + /** + * @param size + * @see jalview.api.ViewStyleI#setFontSize(int) + */ + public void setFontSize(int size) + { + viewStyle.setFontSize(size); + } /** - * gui state - changes to colour scheme propagated to all groups + * @return + * @see jalview.api.ViewStyleI#getFontStyle() */ - private boolean colourAppliesToAllGroups; + public int getFontStyle() + { + return viewStyle.getFontStyle(); + } /** - * @param value - * indicating if subsequent colourscheme changes will be propagated - * to all groups + * @return + * @see jalview.api.ViewStyleI#getFontName() */ - public void setColourAppliesToAllGroups(boolean b) + public String getFontName() { - colourAppliesToAllGroups = b; + return viewStyle.getFontName(); } /** - * - * - * @return flag indicating if colourchanges propagated to all groups + * @return + * @see jalview.api.ViewStyleI#getFontSize() */ - public boolean getColourAppliesToAllGroups() + public int getFontSize() { - return colourAppliesToAllGroups; + return viewStyle.getFontSize(); } - boolean abovePIDThreshold = false; + /** + * @param upperCasebold + * @see jalview.api.ViewStyleI#setUpperCasebold(boolean) + */ + public void setUpperCasebold(boolean upperCasebold) + { + viewStyle.setUpperCasebold(upperCasebold); + } /** - * GUI state - * - * @return true if percent identity threshold is applied to shading + * @return + * @see jalview.api.ViewStyleI#isUpperCasebold() */ - public boolean getAbovePIDThreshold() + public boolean isUpperCasebold() { - return abovePIDThreshold; + return viewStyle.isUpperCasebold(); } /** - * GUI state - * - * - * @param b - * indicate if percent identity threshold is applied to shading + * @return + * @see jalview.api.ViewStyleI#isSeqNameItalics() */ - public void setAbovePIDThreshold(boolean b) + public boolean isSeqNameItalics() { - abovePIDThreshold = b; + return viewStyle.isSeqNameItalics(); } - int threshold; + /** + * @param colourByReferenceSeq + * @see jalview.api.ViewStyleI#setColourByReferenceSeq(boolean) + */ + public void setColourByReferenceSeq(boolean colourByReferenceSeq) + { + viewStyle.setColourByReferenceSeq(colourByReferenceSeq); + } /** - * DOCUMENT ME! - * - * @param thresh - * DOCUMENT ME! + * @param b + * @see jalview.api.ViewStyleI#setColourAppliesToAllGroups(boolean) */ - public void setThreshold(int thresh) + public void setColourAppliesToAllGroups(boolean b) { - threshold = thresh; + viewStyle.setColourAppliesToAllGroups(b); } /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! + * @return + * @see jalview.api.ViewStyleI#getColourAppliesToAllGroups() */ - public int getThreshold() + public boolean getColourAppliesToAllGroups() { - return threshold; + return viewStyle.getColourAppliesToAllGroups(); } - int increment; + /** + * @return + * @see jalview.api.ViewStyleI#getAbovePIDThreshold() + */ + public boolean getAbovePIDThreshold() + { + return viewStyle.getAbovePIDThreshold(); + } /** - * * @param inc - * set the scalar for bleaching colourschemes according to degree of - * conservation + * @see jalview.api.ViewStyleI#setIncrement(int) */ public void setIncrement(int inc) { - increment = inc; + viewStyle.setIncrement(inc); } /** - * GUI State - * - * @return get scalar for bleaching colourschemes by conservation + * @return + * @see jalview.api.ViewStyleI#getIncrement() */ public int getIncrement() { - return increment; + return viewStyle.getIncrement(); } - boolean conservationColourSelected = false; - /** - * GUI state - * - * @return true if conservation based shading is enabled + * @param b + * @see jalview.api.ViewStyleI#setConservationSelected(boolean) */ - public boolean getConservationSelected() + public void setConservationSelected(boolean b) { - return conservationColourSelected; + viewStyle.setConservationSelected(b); } /** - * GUI state - * - * @param b - * enable conservation based shading + * @param show + * @see jalview.api.ViewStyleI#setShowHiddenMarkers(boolean) */ - public void setConservationSelected(boolean b) + public void setShowHiddenMarkers(boolean show) { - conservationColourSelected = b; + viewStyle.setShowHiddenMarkers(show); } - @Override - public void setGlobalColourScheme(ColourSchemeI cs) + /** + * @return + * @see jalview.api.ViewStyleI#getShowHiddenMarkers() + */ + public boolean getShowHiddenMarkers() { - // TODO: logic refactored from AlignFrame changeColour - - // autorecalc stuff should be changed to rely on the worker system - // check to see if we should implement a changeColour(cs) method rather than - // put th logic in here - // - means that caller decides if they want to just modify state and defer - // calculation till later or to do all calculations in thread. - // via changecolour - globalColourScheme = cs; - boolean recalc = false; - if (cs != null) - { - cs.setConservationApplied(recalc = getConservationSelected()); - if (getAbovePIDThreshold() || cs instanceof PIDColourScheme - || cs instanceof Blosum62ColourScheme) - { - recalc = true; - cs.setThreshold(threshold, ignoreGapsInConsensusCalculation); - } - else - { - cs.setThreshold(0, ignoreGapsInConsensusCalculation); - } - if (recalc) - { - cs.setConsensus(hconsensus); - cs.setConservation(hconservation); - } - cs.alignmentChanged(alignment, hiddenRepSequences); - } - if (getColourAppliesToAllGroups()) - { - for (SequenceGroup sg : getAlignment().getGroups()) - { - if (cs == null) - { - sg.cs = null; - continue; - } - sg.cs = cs.applyTo(sg, getHiddenRepSequences()); - sg.setConsPercGaps(ConsPercGaps); - if (getAbovePIDThreshold() || cs instanceof PIDColourScheme - || cs instanceof Blosum62ColourScheme) - { - sg.cs.setThreshold(threshold, getIgnoreGapsConsensus()); - recalc = true; - } - else - { - sg.cs.setThreshold(0, getIgnoreGapsConsensus()); - } - - if (getConservationSelected()) - { - sg.cs.setConservationApplied(true); - recalc = true; - } - else - { - sg.cs.setConservation(null); - // sg.cs.setThreshold(0, getIgnoreGapsConsensus()); - } - if (recalc) - { - sg.recalcConservation(); - } - else - { - sg.cs.alignmentChanged(sg, hiddenRepSequences); - } - } - } - + return viewStyle.getShowHiddenMarkers(); } - @Override - public ColourSchemeI getGlobalColourScheme() + /** + * @param b + * @see jalview.api.ViewStyleI#setScaleRightWrapped(boolean) + */ + public void setScaleRightWrapped(boolean b) { - return globalColourScheme; + viewStyle.setScaleRightWrapped(b); } - protected AlignmentAnnotation consensus; - - protected AlignmentAnnotation strucConsensus; - - protected AlignmentAnnotation conservation; - - protected AlignmentAnnotation quality; - - protected AlignmentAnnotation[] groupConsensus; - - protected AlignmentAnnotation[] groupConservation; - /** - * results of alignment consensus analysis for visible portion of view + * @param b + * @see jalview.api.ViewStyleI#setScaleLeftWrapped(boolean) */ - protected Hashtable[] hconsensus = null; + public void setScaleLeftWrapped(boolean b) + { + viewStyle.setScaleLeftWrapped(b); + } /** - * results of secondary structure base pair consensus for visible portion of - * view + * @param b + * @see jalview.api.ViewStyleI#setScaleAboveWrapped(boolean) */ - protected Hashtable[] hStrucConsensus = null; - - protected Conservation hconservation = null; - - @Override - public void setConservation(Conservation cons) + public void setScaleAboveWrapped(boolean b) { - hconservation = cons; + viewStyle.setScaleAboveWrapped(b); } /** - * percentage gaps allowed in a column before all amino acid properties should - * be considered unconserved + * @return + * @see jalview.api.ViewStyleI#getScaleLeftWrapped() */ - int ConsPercGaps = 25; // JBPNote : This should be a scalable property! - - @Override - public int getConsPercGaps() + public boolean getScaleLeftWrapped() { - return ConsPercGaps; + return viewStyle.getScaleLeftWrapped(); } - @Override - public void setSequenceConsensusHash(Hashtable[] hconsensus) + /** + * @return + * @see jalview.api.ViewStyleI#getScaleAboveWrapped() + */ + public boolean getScaleAboveWrapped() { - this.hconsensus = hconsensus; - + return viewStyle.getScaleAboveWrapped(); } - @Override - public Hashtable[] getSequenceConsensusHash() + /** + * @return + * @see jalview.api.ViewStyleI#getScaleRightWrapped() + */ + public boolean getScaleRightWrapped() { - return hconsensus; + return viewStyle.getScaleRightWrapped(); } - @Override - public Hashtable[] getRnaStructureConsensusHash() + /** + * @param b + * @see jalview.api.ViewStyleI#setAbovePIDThreshold(boolean) + */ + public void setAbovePIDThreshold(boolean b) { - return hStrucConsensus; + viewStyle.setAbovePIDThreshold(b); } - @Override - public void setRnaStructureConsensusHash(Hashtable[] hStrucConsensus) + /** + * @param thresh + * @see jalview.api.ViewStyleI#setThreshold(int) + */ + public void setThreshold(int thresh) { - this.hStrucConsensus = hStrucConsensus; - + viewStyle.setThreshold(thresh); } - @Override - public AlignmentAnnotation getAlignmentQualityAnnot() + /** + * @return + * @see jalview.api.ViewStyleI#getThreshold() + */ + public int getThreshold() { - return quality; + return viewStyle.getThreshold(); } - @Override - public AlignmentAnnotation getAlignmentConservationAnnotation() + /** + * @return + * @see jalview.api.ViewStyleI#getShowJVSuffix() + */ + public boolean getShowJVSuffix() { - return conservation; + return viewStyle.getShowJVSuffix(); } - @Override - public AlignmentAnnotation getAlignmentConsensusAnnotation() + /** + * @param b + * @see jalview.api.ViewStyleI#setShowJVSuffix(boolean) + */ + public void setShowJVSuffix(boolean b) { - return consensus; + viewStyle.setShowJVSuffix(b); } - @Override - public AlignmentAnnotation getAlignmentStrucConsensusAnnotation() + /** + * @param state + * @see jalview.api.ViewStyleI#setWrapAlignment(boolean) + */ + public void setWrapAlignment(boolean state) { - return strucConsensus; + viewStyle.setWrapAlignment(state); } - protected AlignCalcManagerI calculator = new AlignCalcManager(); + /** + * @param state + * @see jalview.api.ViewStyleI#setShowText(boolean) + */ + public void setShowText(boolean state) + { + viewStyle.setShowText(state); + } /** - * trigger update of conservation annotation + * @param state + * @see jalview.api.ViewStyleI#setRenderGaps(boolean) */ - public void updateConservation(final AlignmentViewPanel ap) + public void setRenderGaps(boolean state) { - // see note in mantis : issue number 8585 - if (alignment.isNucleotide() || conservation == null - || !autoCalculateConsensus) - { - return; - } - if (calculator - .getRegisteredWorkersOfClass(jalview.workers.ConservationThread.class) == null) - { - calculator.registerWorker(new jalview.workers.ConservationThread( - this, ap)); - } + viewStyle.setRenderGaps(state); } /** - * trigger update of consensus annotation + * @return + * @see jalview.api.ViewStyleI#getColourText() */ - public void updateConsensus(final AlignmentViewPanel ap) - { - // see note in mantis : issue number 8585 - if (consensus == null || !autoCalculateConsensus) - { - return; - } - if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null) - { - calculator.registerWorker(new ConsensusThread(this, ap)); - } - } - - // --------START Structure Conservation - public void updateStrucConsensus(final AlignmentViewPanel ap) - { - if (autoCalculateStrucConsensus && strucConsensus == null - && alignment.isNucleotide() && alignment.hasRNAStructure()) - { - // secondary structure has been added - so init the consensus line - initRNAStructure(); - } - - // see note in mantis : issue number 8585 - if (strucConsensus == null || !autoCalculateStrucConsensus) - { - return; - } - if (calculator.getRegisteredWorkersOfClass(StrucConsensusThread.class) == null) - { - calculator.registerWorker(new StrucConsensusThread(this, ap)); - } - } - - public boolean isCalcInProgress() - { - return calculator.isWorking(); - } - - @Override - public boolean isCalculationInProgress( - AlignmentAnnotation alignmentAnnotation) - { - if (!alignmentAnnotation.autoCalculated) - return false; - if (calculator.workingInvolvedWith(alignmentAnnotation)) - { - // System.err.println("grey out ("+alignmentAnnotation.label+")"); - return true; - } - return false; - } - - @Override - public boolean isClosed() - { - // TODO: check that this isClosed is only true after panel is closed, not - // before it is fully constructed. - return alignment == null; - } - - @Override - public AlignCalcManagerI getCalcManager() + public boolean getColourText() { - return calculator; + return viewStyle.getColourText(); } /** - * should conservation rows be shown for groups - */ - protected boolean showGroupConservation = false; - - /** - * should consensus rows be shown for groups - */ - protected boolean showGroupConsensus = false; - - /** - * should consensus profile be rendered by default - */ - protected boolean showSequenceLogo = false; - - /** - * should consensus profile be rendered normalised to row height - */ - protected boolean normaliseSequenceLogo = false; - - /** - * should consensus histograms be rendered by default - */ - protected boolean showConsensusHistogram = true; - - /** - * @return the showConsensusProfile + * @param state + * @see jalview.api.ViewStyleI#setColourText(boolean) */ - @Override - public boolean isShowSequenceLogo() + public void setColourText(boolean state) { - return showSequenceLogo; + viewStyle.setColourText(state); } /** - * @param showSequenceLogo - * the new value + * @return + * @see jalview.api.ViewStyleI#getWrapAlignment() */ - public void setShowSequenceLogo(boolean showSequenceLogo) + public boolean getWrapAlignment() { - if (showSequenceLogo != this.showSequenceLogo) - { - // TODO: decouple settings setting from calculation when refactoring - // annotation update method from alignframe to viewport - this.showSequenceLogo = showSequenceLogo; - calculator.updateAnnotationFor(ConsensusThread.class); - calculator.updateAnnotationFor(StrucConsensusThread.class); - } - this.showSequenceLogo = showSequenceLogo; + return viewStyle.getWrapAlignment(); } /** - * @param showConsensusHistogram - * the showConsensusHistogram to set + * @return + * @see jalview.api.ViewStyleI#getShowText() */ - public void setShowConsensusHistogram(boolean showConsensusHistogram) + public boolean getShowText() { - this.showConsensusHistogram = showConsensusHistogram; + return viewStyle.getShowText(); } /** - * @return the showGroupConservation + * @return + * @see jalview.api.ViewStyleI#getWrappedWidth() */ - public boolean isShowGroupConservation() + public int getWrappedWidth() { - return showGroupConservation; + return viewStyle.getWrappedWidth(); } /** - * @param showGroupConservation - * the showGroupConservation to set + * @param w + * @see jalview.api.ViewStyleI#setWrappedWidth(int) */ - public void setShowGroupConservation(boolean showGroupConservation) + public void setWrappedWidth(int w) { - this.showGroupConservation = showGroupConservation; + viewStyle.setWrappedWidth(w); } /** - * @return the showGroupConsensus + * @return + * @see jalview.api.ViewStyleI#getCharHeight() */ - public boolean isShowGroupConsensus() + public int getCharHeight() { - return showGroupConsensus; + return viewStyle.getCharHeight(); } /** - * @param showGroupConsensus - * the showGroupConsensus to set + * @param h + * @see jalview.api.ViewStyleI#setCharHeight(int) */ - public void setShowGroupConsensus(boolean showGroupConsensus) + public void setCharHeight(int h) { - this.showGroupConsensus = showGroupConsensus; + viewStyle.setCharHeight(h); } /** - * - * @return flag to indicate if the consensus histogram should be rendered by - * default + * @return + * @see jalview.api.ViewStyleI#getCharWidth() */ - @Override - public boolean isShowConsensusHistogram() + public int getCharWidth() { - return this.showConsensusHistogram; + return viewStyle.getCharWidth(); } /** - * show non-conserved residues only + * @param w + * @see jalview.api.ViewStyleI#setCharWidth(int) */ - protected boolean showUnconserved = false; + public void setCharWidth(int w) + { + viewStyle.setCharWidth(w); + } /** - * when set, updateAlignment will always ensure sequences are of equal length + * @return + * @see jalview.api.ViewStyleI#getShowBoxes() */ - private boolean padGaps = false; + public boolean getShowBoxes() + { + return viewStyle.getShowBoxes(); + } /** - * when set, alignment should be reordered according to a newly opened tree + * @return + * @see jalview.api.ViewStyleI#getShowUnconserved() */ - public boolean sortByTree = false; - public boolean getShowUnconserved() { - return showUnconserved; - } - - public void setShowUnconserved(boolean showunconserved) - { - showUnconserved = showunconserved; + return viewStyle.getShowUnconserved(); } /** - * @param showNonconserved - * the showUnconserved to set + * @param showunconserved + * @see jalview.api.ViewStyleI#setShowUnconserved(boolean) */ - public void setShowunconserved(boolean displayNonconserved) + public void setShowUnconserved(boolean showunconserved) { - this.showUnconserved = displayNonconserved; + viewStyle.setShowUnconserved(showunconserved); } /** - * - * - * @return null or the currently selected sequence region + * @param default1 + * @see jalview.api.ViewStyleI#setSeqNameItalics(boolean) */ - @Override - public SequenceGroup getSelectionGroup() + public void setSeqNameItalics(boolean default1) { - return selectionGroup; + viewStyle.setSeqNameItalics(default1); } /** - * Set the selection group for this window. - * - * @param sg - * - group holding references to sequences in this alignment view - * + * alignment displayed in the viewport. Please use get/setter */ - @Override - public void setSelectionGroup(SequenceGroup sg) - { - selectionGroup = sg; - } + protected AlignmentI alignment; - public void setHiddenColumns(ColumnSelection colsel) + @Override + public AlignmentI getAlignment() { - this.colSel = colsel; - if (colSel.getHiddenColumns() != null) - { - hasHiddenColumns = true; - } + return alignment; } @Override - public ColumnSelection getColumnSelection() + public char getGapCharacter() { - return colSel; + return alignment.getGapCharacter(); } - public void setColumnSelection(ColumnSelection colSel) - { - this.colSel = colSel; - } + protected String sequenceSetID; /** - * - * @return + * probably unused indicator that view is of a dataset rather than an + * alignment */ - @Override - public Map getHiddenRepSequences() - { - return hiddenRepSequences; - } + protected boolean isDataset = false; - @Override - public void setHiddenRepSequences( - Map hiddenRepSequences) + public void setDataset(boolean b) { - this.hiddenRepSequences = hiddenRepSequences; + isDataset = b; } - protected boolean hasHiddenColumns = false; - - public void updateHiddenColumns() + public boolean isDataset() { - hasHiddenColumns = colSel.getHiddenColumns() != null; + return isDataset; } - protected boolean hasHiddenRows = false; - - public boolean hasHiddenRows() - { - return hasHiddenRows; - } + private Map hiddenRepSequences; - protected SequenceGroup selectionGroup; + protected ColumnSelection colSel = new ColumnSelection(); - public void setSequenceSetId(String newid) - { - if (sequenceSetID != null) - { - System.err - .println("Warning - overwriting a sequenceSetId for a viewport!"); - } - sequenceSetID = new String(newid); - } + public boolean autoCalculateConsensus = true; - @Override - public String getSequenceSetId() - { - if (sequenceSetID == null) - { - sequenceSetID = alignment.hashCode() + ""; - } + protected boolean autoCalculateStrucConsensus = true; - return sequenceSetID; - } + protected boolean ignoreGapsInConsensusCalculation = false; - /** - * unique viewId for synchronizing state (e.g. with stored Jalview Project) - * - */ - protected String viewId = null; + protected ColourSchemeI globalColourScheme = null; - public String getViewId() + @Override + public void setGlobalColourScheme(ColourSchemeI cs) { - if (viewId == null) + // TODO: logic refactored from AlignFrame changeColour - + // TODO: autorecalc stuff should be changed to rely on the worker system + // check to see if we should implement a changeColour(cs) method rather than + // put th logic in here + // - means that caller decides if they want to just modify state and defer + // calculation till later or to do all calculations in thread. + // via changecolour + globalColourScheme = cs; + boolean recalc = false; + if (cs != null) + { + cs.setConservationApplied(recalc = getConservationSelected()); + if (getAbovePIDThreshold() || cs instanceof PIDColourScheme + || cs instanceof Blosum62ColourScheme) + { + recalc = true; + cs.setThreshold(viewStyle.getThreshold(), + ignoreGapsInConsensusCalculation); + } + else + { + cs.setThreshold(0, ignoreGapsInConsensusCalculation); + } + if (recalc) + { + cs.setConsensus(hconsensus); + cs.setConservation(hconservation); + } + cs.alignmentChanged(alignment, hiddenRepSequences); + } + if (getColourAppliesToAllGroups()) + { + for (SequenceGroup sg : getAlignment().getGroups()) + { + if (cs == null) + { + sg.cs = null; + continue; + } + sg.cs = cs.applyTo(sg, getHiddenRepSequences()); + sg.setConsPercGaps(ConsPercGaps); + if (getAbovePIDThreshold() || cs instanceof PIDColourScheme + || cs instanceof Blosum62ColourScheme) + { + sg.cs.setThreshold(viewStyle.getThreshold(), + isIgnoreGapsConsensus()); + recalc = true; + } + else + { + sg.cs.setThreshold(0, isIgnoreGapsConsensus()); + } + + if (getConservationSelected()) + { + sg.cs.setConservationApplied(true); + recalc = true; + } + else + { + sg.cs.setConservation(null); + // sg.cs.setThreshold(0, getIgnoreGapsConsensus()); + } + if (recalc) + { + sg.recalcConservation(); + } + else + { + sg.cs.alignmentChanged(sg, hiddenRepSequences); + } + } + } + } + + @Override + public ColourSchemeI getGlobalColourScheme() + { + return globalColourScheme; + } + + protected AlignmentAnnotation consensus; + + protected AlignmentAnnotation complementConsensus; + + protected AlignmentAnnotation strucConsensus; + + protected AlignmentAnnotation conservation; + + protected AlignmentAnnotation quality; + + protected AlignmentAnnotation[] groupConsensus; + + protected AlignmentAnnotation[] groupConservation; + + /** + * results of alignment consensus analysis for visible portion of view + */ + protected Hashtable[] hconsensus = null; + + /** + * results of cDNA complement consensus visible portion of view + */ + protected Hashtable[] hcomplementConsensus = null; + + /** + * results of secondary structure base pair consensus for visible portion of + * view + */ + protected Hashtable[] hStrucConsensus = null; + + protected Conservation hconservation = null; + + @Override + public void setConservation(Conservation cons) + { + hconservation = cons; + } + + /** + * percentage gaps allowed in a column before all amino acid properties should + * be considered unconserved + */ + int ConsPercGaps = 25; // JBPNote : This should be a scalable property! + + @Override + public int getConsPercGaps() + { + return ConsPercGaps; + } + + @Override + public void setSequenceConsensusHash(Hashtable[] hconsensus) + { + this.hconsensus = hconsensus; + } + + @Override + public void setComplementConsensusHash(Hashtable[] hconsensus) + { + this.hcomplementConsensus = hconsensus; + } + + @Override + public Hashtable[] getSequenceConsensusHash() + { + return hconsensus; + } + + @Override + public Hashtable[] getComplementConsensusHash() + { + return hcomplementConsensus; + } + + @Override + public Hashtable[] getRnaStructureConsensusHash() + { + return hStrucConsensus; + } + + @Override + public void setRnaStructureConsensusHash(Hashtable[] hStrucConsensus) + { + this.hStrucConsensus = hStrucConsensus; + + } + + @Override + public AlignmentAnnotation getAlignmentQualityAnnot() + { + return quality; + } + + @Override + public AlignmentAnnotation getAlignmentConservationAnnotation() + { + return conservation; + } + + @Override + public AlignmentAnnotation getAlignmentConsensusAnnotation() + { + return consensus; + } + + @Override + public AlignmentAnnotation getComplementConsensusAnnotation() + { + return complementConsensus; + } + + @Override + public AlignmentAnnotation getAlignmentStrucConsensusAnnotation() + { + return strucConsensus; + } + + protected AlignCalcManagerI calculator = new AlignCalcManager(); + + /** + * trigger update of conservation annotation + */ + public void updateConservation(final AlignmentViewPanel ap) + { + // see note in mantis : issue number 8585 + if (alignment.isNucleotide() || conservation == null + || !autoCalculateConsensus) + { + return; + } + if (calculator + .getRegisteredWorkersOfClass(jalview.workers.ConservationThread.class) == null) + { + calculator.registerWorker(new jalview.workers.ConservationThread( + this, ap)); + } + } + + /** + * trigger update of consensus annotation + */ + public void updateConsensus(final AlignmentViewPanel ap) + { + // see note in mantis : issue number 8585 + if (consensus == null || !autoCalculateConsensus) + { + return; + } + if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null) + { + calculator.registerWorker(new ConsensusThread(this, ap)); + } + + /* + * A separate thread to compute cDNA consensus for a protein alignment + */ + final AlignmentI al = this.getAlignment(); + if (!al.isNucleotide() && al.getCodonFrames() != null + && !al.getCodonFrames().isEmpty()) + { + if (calculator + .getRegisteredWorkersOfClass(ComplementConsensusThread.class) == null) + { + calculator.registerWorker(new ComplementConsensusThread(this, ap)); + } + } + } + + // --------START Structure Conservation + public void updateStrucConsensus(final AlignmentViewPanel ap) + { + if (autoCalculateStrucConsensus && strucConsensus == null + && alignment.isNucleotide() && alignment.hasRNAStructure()) + { + // secondary structure has been added - so init the consensus line + initRNAStructure(); + } + + // see note in mantis : issue number 8585 + if (strucConsensus == null || !autoCalculateStrucConsensus) + { + return; + } + if (calculator.getRegisteredWorkersOfClass(StrucConsensusThread.class) == null) + { + calculator.registerWorker(new StrucConsensusThread(this, ap)); + } + } + + public boolean isCalcInProgress() + { + return calculator.isWorking(); + } + + @Override + public boolean isCalculationInProgress( + AlignmentAnnotation alignmentAnnotation) + { + if (!alignmentAnnotation.autoCalculated) + { + return false; + } + if (calculator.workingInvolvedWith(alignmentAnnotation)) + { + // System.err.println("grey out ("+alignmentAnnotation.label+")"); + return true; + } + return false; + } + + @Override + public boolean isClosed() + { + // TODO: check that this isClosed is only true after panel is closed, not + // before it is fully constructed. + return alignment == null; + } + + @Override + public AlignCalcManagerI getCalcManager() + { + return calculator; + } + + /** + * should conservation rows be shown for groups + */ + protected boolean showGroupConservation = false; + + /** + * should consensus rows be shown for groups + */ + protected boolean showGroupConsensus = false; + + /** + * should consensus profile be rendered by default + */ + protected boolean showSequenceLogo = false; + + /** + * should consensus profile be rendered normalised to row height + */ + protected boolean normaliseSequenceLogo = false; + + /** + * should consensus histograms be rendered by default + */ + protected boolean showConsensusHistogram = true; + + /** + * @return the showConsensusProfile + */ + @Override + public boolean isShowSequenceLogo() + { + return showSequenceLogo; + } + + /** + * @param showSequenceLogo + * the new value + */ + public void setShowSequenceLogo(boolean showSequenceLogo) + { + if (showSequenceLogo != this.showSequenceLogo) + { + // TODO: decouple settings setting from calculation when refactoring + // annotation update method from alignframe to viewport + this.showSequenceLogo = showSequenceLogo; + calculator.updateAnnotationFor(ConsensusThread.class); + calculator.updateAnnotationFor(ComplementConsensusThread.class); + calculator.updateAnnotationFor(StrucConsensusThread.class); + } + this.showSequenceLogo = showSequenceLogo; + } + + /** + * @param showConsensusHistogram + * the showConsensusHistogram to set + */ + public void setShowConsensusHistogram(boolean showConsensusHistogram) + { + this.showConsensusHistogram = showConsensusHistogram; + } + + /** + * @return the showGroupConservation + */ + public boolean isShowGroupConservation() + { + return showGroupConservation; + } + + /** + * @param showGroupConservation + * the showGroupConservation to set + */ + public void setShowGroupConservation(boolean showGroupConservation) + { + this.showGroupConservation = showGroupConservation; + } + + /** + * @return the showGroupConsensus + */ + public boolean isShowGroupConsensus() + { + return showGroupConsensus; + } + + /** + * @param showGroupConsensus + * the showGroupConsensus to set + */ + public void setShowGroupConsensus(boolean showGroupConsensus) + { + this.showGroupConsensus = showGroupConsensus; + } + + /** + * + * @return flag to indicate if the consensus histogram should be rendered by + * default + */ + @Override + public boolean isShowConsensusHistogram() + { + return this.showConsensusHistogram; + } + + /** + * when set, updateAlignment will always ensure sequences are of equal length + */ + private boolean padGaps = false; + + /** + * when set, alignment should be reordered according to a newly opened tree + */ + public boolean sortByTree = false; + + /** + * + * + * @return null or the currently selected sequence region + */ + @Override + public SequenceGroup getSelectionGroup() + { + return selectionGroup; + } + + /** + * Set the selection group for this window. + * + * @param sg + * - group holding references to sequences in this alignment view + * + */ + @Override + public void setSelectionGroup(SequenceGroup sg) + { + selectionGroup = sg; + } + + public void setHiddenColumns(ColumnSelection colsel) + { + this.colSel = colsel; + } + + @Override + public ColumnSelection getColumnSelection() + { + return colSel; + } + + @Override + public void setColumnSelection(ColumnSelection colSel) + { + this.colSel = colSel; + if (colSel != null) + { + updateHiddenColumns(); + } + } + + /** + * + * @return + */ + @Override + public Map getHiddenRepSequences() + { + return hiddenRepSequences; + } + + @Override + public void setHiddenRepSequences( + Map hiddenRepSequences) + { + this.hiddenRepSequences = hiddenRepSequences; + } + + @Override + public boolean hasHiddenColumns() + { + return colSel != null && colSel.hasHiddenColumns(); + } + + public void updateHiddenColumns() + { + // this method doesn't really do anything now. But - it could, since a + // column Selection could be in the process of modification + // hasHiddenColumns = colSel.hasHiddenColumns(); + } + + @Override + public boolean hasHiddenRows() + { + return alignment.getHiddenSequences().getSize() > 0; + } + + protected SequenceGroup selectionGroup; + + public void setSequenceSetId(String newid) + { + if (sequenceSetID != null) + { + System.err + .println("Warning - overwriting a sequenceSetId for a viewport!"); + } + sequenceSetID = new String(newid); + } + + @Override + public String getSequenceSetId() + { + if (sequenceSetID == null) + { + sequenceSetID = alignment.hashCode() + ""; + } + + return sequenceSetID; + } + + /** + * unique viewId for synchronizing state (e.g. with stored Jalview Project) + * + */ + protected String viewId = null; + + @Override + public String getViewId() + { + if (viewId == null) { viewId = this.getSequenceSetId() + "." + this.hashCode() + ""; } - return viewId; + return viewId; + } + + public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap) + { + ignoreGapsInConsensusCalculation = b; + if (ap != null) + { + updateConsensus(ap); + if (globalColourScheme != null) + { + globalColourScheme.setThreshold(globalColourScheme.getThreshold(), + ignoreGapsInConsensusCalculation); + } + } + + } + + private long sgrouphash = -1, colselhash = -1; + + /** + * checks current SelectionGroup against record of last hash value, and + * updates record. + * + * @param b + * update the record of last hash value + * + * @return true if SelectionGroup changed since last call (when b is true) + */ + public boolean isSelectionGroupChanged(boolean b) + { + int hc = (selectionGroup == null || selectionGroup.getSize() == 0) ? -1 + : selectionGroup.hashCode(); + if (hc != -1 && hc != sgrouphash) + { + if (b) + { + sgrouphash = hc; + } + return true; + } + return false; + } + + /** + * checks current colsel against record of last hash value, and optionally + * updates record. + * + * @param b + * update the record of last hash value + * @return true if colsel changed since last call (when b is true) + */ + public boolean isColSelChanged(boolean b) + { + int hc = (colSel == null || colSel.size() == 0) ? -1 : colSel + .hashCode(); + if (hc != -1 && hc != colselhash) + { + if (b) + { + colselhash = hc; + } + return true; + } + return false; + } + + @Override + public boolean isIgnoreGapsConsensus() + { + return ignoreGapsInConsensusCalculation; + } + + // / property change stuff + + // JBPNote Prolly only need this in the applet version. + private final java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport( + this); + + protected boolean showConservation = true; + + protected boolean showQuality = true; + + protected boolean showConsensus = true; + + private Map sequenceColours = new HashMap(); + + protected SequenceAnnotationOrder sortAnnotationsBy = null; + + protected boolean showAutocalculatedAbove; + + /** + * when set, view will scroll to show the highlighted position + */ + private boolean followHighlight = true; + + // TODO private with getters and setters? + public int startRes; + + public int endRes; + + public int startSeq; + + public int endSeq; + + /** + * Property change listener for changes in alignment + * + * @param listener + * DOCUMENT ME! + */ + public void addPropertyChangeListener( + java.beans.PropertyChangeListener listener) + { + changeSupport.addPropertyChangeListener(listener); + } + + /** + * DOCUMENT ME! + * + * @param listener + * DOCUMENT ME! + */ + public void removePropertyChangeListener( + java.beans.PropertyChangeListener listener) + { + changeSupport.removePropertyChangeListener(listener); + } + + /** + * Property change listener for changes in alignment + * + * @param prop + * DOCUMENT ME! + * @param oldvalue + * DOCUMENT ME! + * @param newvalue + * DOCUMENT ME! + */ + public void firePropertyChange(String prop, Object oldvalue, + Object newvalue) + { + changeSupport.firePropertyChange(prop, oldvalue, newvalue); + } + + // common hide/show column stuff + + public void hideSelectedColumns() + { + if (colSel.size() < 1) + { + return; + } + + colSel.hideSelectedColumns(); + setSelectionGroup(null); + + } + + public void hideColumns(int start, int end) + { + if (start == end) + { + colSel.hideColumns(start); + } + else + { + colSel.hideColumns(start, end); + } + } + + public void showColumn(int col) + { + colSel.revealHiddenColumns(col); + + } + + public void showAllHiddenColumns() + { + colSel.revealAllHiddenColumns(); + } + + // common hide/show seq stuff + public void showAllHiddenSeqs() + { + if (alignment.getHiddenSequences().getSize() > 0) + { + if (selectionGroup == null) + { + selectionGroup = new SequenceGroup(); + selectionGroup.setEndRes(alignment.getWidth() - 1); + } + List tmp = alignment.getHiddenSequences().showAll( + hiddenRepSequences); + for (SequenceI seq : tmp) + { + selectionGroup.addSequence(seq, false); + setSequenceAnnotationsVisible(seq, true); + } + + hiddenRepSequences = null; + + firePropertyChange("alignment", null, alignment.getSequences()); + // used to set hasHiddenRows/hiddenRepSequences here, after the property + // changed event + sendSelection(); + } + } + + public void showSequence(int index) + { + List tmp = alignment.getHiddenSequences().showSequence( + index, hiddenRepSequences); + if (tmp.size() > 0) + { + if (selectionGroup == null) + { + selectionGroup = new SequenceGroup(); + selectionGroup.setEndRes(alignment.getWidth() - 1); + } + + for (SequenceI seq : tmp) + { + selectionGroup.addSequence(seq, false); + setSequenceAnnotationsVisible(seq, true); + } + firePropertyChange("alignment", null, alignment.getSequences()); + sendSelection(); + } + } + + public void hideAllSelectedSeqs() + { + if (selectionGroup == null || selectionGroup.getSize() < 1) + { + return; + } + + SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment); + + hideSequence(seqs); + + setSelectionGroup(null); + } + + public void hideSequence(SequenceI[] seq) + { + if (seq != null) + { + for (int i = 0; i < seq.length; i++) + { + alignment.getHiddenSequences().hideSequence(seq[i]); + setSequenceAnnotationsVisible(seq[i], false); + } + firePropertyChange("alignment", null, alignment.getSequences()); + } + } + + /** + * Set visibility for any annotations for the given sequence. + * + * @param sequenceI + */ + protected void setSequenceAnnotationsVisible(SequenceI sequenceI, + boolean visible) + { + for (AlignmentAnnotation ann : alignment.getAlignmentAnnotation()) + { + if (ann.sequenceRef == sequenceI) + { + ann.visible = visible; + } + } + } + + public void hideRepSequences(SequenceI repSequence, SequenceGroup sg) + { + int sSize = sg.getSize(); + if (sSize < 2) + { + return; + } + + if (hiddenRepSequences == null) + { + hiddenRepSequences = new Hashtable(); + } + + hiddenRepSequences.put(repSequence, sg); + + // Hide all sequences except the repSequence + SequenceI[] seqs = new SequenceI[sSize - 1]; + int index = 0; + for (int i = 0; i < sSize; i++) + { + if (sg.getSequenceAt(i) != repSequence) + { + if (index == sSize - 1) + { + return; + } + + seqs[index++] = sg.getSequenceAt(i); + } + } + sg.setSeqrep(repSequence); // note: not done in 2.7applet + sg.setHidereps(true); // note: not done in 2.7applet + hideSequence(seqs); + + } + + public boolean isHiddenRepSequence(SequenceI seq) + { + return alignment.getSeqrep() == seq + || (hiddenRepSequences != null && hiddenRepSequences + .containsKey(seq)); + } + + public SequenceGroup getRepresentedSequences(SequenceI seq) + { + return (SequenceGroup) (hiddenRepSequences == null ? null + : hiddenRepSequences.get(seq)); + } + + @Override + public int adjustForHiddenSeqs(int alignmentIndex) + { + return alignment.getHiddenSequences().adjustForHiddenSeqs( + alignmentIndex); + } + + @Override + public void invertColumnSelection() + { + colSel.invertColumnSelection(0, alignment.getWidth()); + } + + @Override + public SequenceI[] getSelectionAsNewSequence() + { + SequenceI[] sequences; + // JBPNote: Need to test jalviewLite.getSelectedSequencesAsAlignmentFrom - + // this was the only caller in the applet for this method + // JBPNote: in applet, this method returned references to the alignment + // sequences, and it did not honour the presence/absence of annotation + // attached to the alignment (probably!) + if (selectionGroup == null || selectionGroup.getSize() == 0) + { + sequences = alignment.getSequencesArray(); + AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation(); + for (int i = 0; i < sequences.length; i++) + { + // construct new sequence with subset of visible annotation + sequences[i] = new Sequence(sequences[i], annots); + } + } + else + { + sequences = selectionGroup.getSelectionAsNewSequences(alignment); + } + + return sequences; + } + + @Override + public SequenceI[] getSequenceSelection() + { + SequenceI[] sequences = null; + if (selectionGroup != null) + { + sequences = selectionGroup.getSequencesInOrder(alignment); + } + if (sequences == null) + { + sequences = alignment.getSequencesArray(); + } + return sequences; + } + + @Override + public CigarArray getViewAsCigars(boolean selectedRegionOnly) + { + return new CigarArray(alignment, colSel, + (selectedRegionOnly ? selectionGroup : null)); + } + + @Override + public jalview.datamodel.AlignmentView getAlignmentView( + boolean selectedOnly) + { + return getAlignmentView(selectedOnly, false); + } + + @Override + public jalview.datamodel.AlignmentView getAlignmentView( + boolean selectedOnly, boolean markGroups) + { + return new AlignmentView(alignment, colSel, selectionGroup, + colSel != null && colSel.hasHiddenColumns(), selectedOnly, + markGroups); + } + + @Override + public String[] getViewAsString(boolean selectedRegionOnly) + { + String[] selection = null; + SequenceI[] seqs = null; + int i, iSize; + int start = 0, end = 0; + if (selectedRegionOnly && selectionGroup != null) + { + iSize = selectionGroup.getSize(); + seqs = selectionGroup.getSequencesInOrder(alignment); + start = selectionGroup.getStartRes(); + end = selectionGroup.getEndRes() + 1; + } + else + { + iSize = alignment.getHeight(); + seqs = alignment.getSequencesArray(); + end = alignment.getWidth(); + } + + selection = new String[iSize]; + if (colSel != null && colSel.hasHiddenColumns()) + { + selection = colSel.getVisibleSequenceStrings(start, end, seqs); + } + else + { + for (i = 0; i < iSize; i++) + { + selection[i] = seqs[i].getSequenceAsString(start, end); + } + + } + return selection; + } + + @Override + public List getVisibleRegionBoundaries(int min, int max) + { + ArrayList regions = new ArrayList(); + int start = min; + int end = max; + + do + { + if (colSel != null && colSel.hasHiddenColumns()) + { + if (start == 0) + { + start = colSel.adjustForHiddenColumns(start); + } + + end = colSel.getHiddenBoundaryRight(start); + if (start == end) + { + end = max; + } + if (end > max) + { + end = max; + } + } + + regions.add(new int[] { start, end }); + + if (colSel != null && colSel.hasHiddenColumns()) + { + start = colSel.adjustForHiddenColumns(end); + start = colSel.getHiddenBoundaryLeft(start) + 1; + } + } while (end < max); + + int[][] startEnd = new int[regions.size()][2]; + + return regions; + } + + @Override + public List getVisibleAlignmentAnnotation( + boolean selectedOnly) + { + ArrayList ala = new ArrayList(); + AlignmentAnnotation[] aa; + if ((aa = alignment.getAlignmentAnnotation()) != null) + { + for (AlignmentAnnotation annot : aa) + { + AlignmentAnnotation clone = new AlignmentAnnotation(annot); + if (selectedOnly && selectionGroup != null) + { + colSel.makeVisibleAnnotation(selectionGroup.getStartRes(), + selectionGroup.getEndRes(), clone); + } + else + { + colSel.makeVisibleAnnotation(clone); + } + ala.add(clone); + } + } + return ala; + } + + @Override + public boolean isPadGaps() + { + return padGaps; + } + + @Override + public void setPadGaps(boolean padGaps) + { + this.padGaps = padGaps; + } + + /** + * apply any post-edit constraints and trigger any calculations needed after + * an edit has been performed on the alignment + * + * @param ap + */ + @Override + public void alignmentChanged(AlignmentViewPanel ap) + { + if (isPadGaps()) + { + alignment.padGaps(); + } + if (autoCalculateConsensus) + { + updateConsensus(ap); + } + if (hconsensus != null && autoCalculateConsensus) + { + updateConservation(ap); + } + if (autoCalculateStrucConsensus) + { + updateStrucConsensus(ap); + } + + // Reset endRes of groups if beyond alignment width + int alWidth = alignment.getWidth(); + List groups = alignment.getGroups(); + if (groups != null) + { + for (SequenceGroup sg : groups) + { + if (sg.getEndRes() > alWidth) + { + sg.setEndRes(alWidth - 1); + } + } + } + + if (selectionGroup != null && selectionGroup.getEndRes() > alWidth) + { + selectionGroup.setEndRes(alWidth - 1); + } + + resetAllColourSchemes(); + calculator.restartWorkers(); + // alignment.adjustSequenceAnnotations(); } - public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap) + /** + * reset scope and do calculations for all applied colourschemes on alignment + */ + void resetAllColourSchemes() { - ignoreGapsInConsensusCalculation = b; - if (ap != null) + ColourSchemeI cs = globalColourScheme; + if (cs != null) { - updateConsensus(ap); - if (globalColourScheme != null) + cs.alignmentChanged(alignment, hiddenRepSequences); + + cs.setConsensus(hconsensus); + if (cs.conservationApplied()) { - globalColourScheme.setThreshold(globalColourScheme.getThreshold(), - ignoreGapsInConsensusCalculation); + cs.setConservation(Conservation.calculateConservation("All", + ResidueProperties.propHash, 3, alignment.getSequences(), 0, + alignment.getWidth(), false, getConsPercGaps(), false)); } } + for (SequenceGroup sg : alignment.getGroups()) + { + if (sg.cs != null) + { + sg.cs.alignmentChanged(sg, hiddenRepSequences); + } + sg.recalcConservation(); + } } - private long sgrouphash = -1, colselhash = -1; + protected void initAutoAnnotation() + { + // TODO: add menu option action that nulls or creates consensus object + // depending on if the user wants to see the annotation or not in a + // specific alignment + + if (hconsensus == null && !isDataset) + { + if (!alignment.isNucleotide()) + { + initConservation(); + initQuality(); + } + else + { + initRNAStructure(); + } + consensus = new AlignmentAnnotation("Consensus", "PID", + new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); + initConsensus(consensus); + + initComplementConsensus(); + } + } /** - * checks current SelectionGroup against record of last hash value, and - * updates record. - * - * @param b - * update the record of last hash value - * - * @return true if SelectionGroup changed since last call (when b is true) + * If this is a protein alignment and there are mappings to cDNA, add the cDNA + * consensus annotation. */ - public boolean isSelectionGroupChanged(boolean b) + public void initComplementConsensus() { - int hc = (selectionGroup == null || selectionGroup.getSize() == 0) ? -1 - : selectionGroup.hashCode(); - if (hc != -1 && hc != sgrouphash) + if (!alignment.isNucleotide()) { - if (b) + final Set codonMappings = alignment + .getCodonFrames(); + if (codonMappings != null && !codonMappings.isEmpty()) { - sgrouphash = hc; + complementConsensus = new AlignmentAnnotation("cDNA Consensus", + "PID for cDNA", new Annotation[1], 0f, 100f, + AlignmentAnnotation.BAR_GRAPH); + initConsensus(complementConsensus); } - return true; } - return false; } - /** - * checks current colsel against record of last hash value, and optionally - * updates record. + private void initConsensus(AlignmentAnnotation aa) + { + aa.hasText = true; + aa.autoCalculated = true; + + if (showConsensus) + { + alignment.addAnnotation(aa); + } + } + + private void initConservation() + { + if (showConservation) + { + if (conservation == null) + { + conservation = new AlignmentAnnotation("Conservation", + "Conservation of total alignment less than " + + getConsPercGaps() + "% gaps", new Annotation[1], + 0f, 11f, AlignmentAnnotation.BAR_GRAPH); + conservation.hasText = true; + conservation.autoCalculated = true; + alignment.addAnnotation(conservation); + } + } + } + + private void initQuality() + { + if (showQuality) + { + if (quality == null) + { + quality = new AlignmentAnnotation("Quality", + "Alignment Quality based on Blosum62 scores", + new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH); + quality.hasText = true; + quality.autoCalculated = true; + alignment.addAnnotation(quality); + } + } + } + + private void initRNAStructure() + { + if (alignment.hasRNAStructure() && strucConsensus == null) + { + strucConsensus = new AlignmentAnnotation("StrucConsensus", "PID", + new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); + strucConsensus.hasText = true; + strucConsensus.autoCalculated = true; + + if (showConsensus) + { + alignment.addAnnotation(strucConsensus); + } + } + } + + /* + * (non-Javadoc) * - * @param b - * update the record of last hash value - * @return true if colsel changed since last call (when b is true) + * @see jalview.api.AlignViewportI#calcPanelHeight() */ - public boolean isColSelChanged(boolean b) + @Override + public int calcPanelHeight() { - int hc = (colSel == null || colSel.size() == 0) ? -1 : colSel - .hashCode(); - if (hc != -1 && hc != colselhash) + // setHeight of panels + AlignmentAnnotation[] anns = getAlignment().getAlignmentAnnotation(); + int height = 0; + int charHeight = getCharHeight(); + if (anns != null) + { + BitSet graphgrp = new BitSet(); + for (AlignmentAnnotation aa : anns) + { + if (aa == null) + { + System.err.println("Null annotation row: ignoring."); + continue; + } + if (!aa.visible) + { + continue; + } + if (aa.graphGroup > -1) + { + if (graphgrp.get(aa.graphGroup)) + { + continue; + } + else + { + graphgrp.set(aa.graphGroup); + } + } + aa.height = 0; + + if (aa.hasText) + { + aa.height += charHeight; + } + + if (aa.hasIcons) + { + aa.height += 16; + } + + if (aa.graph > 0) + { + aa.height += aa.graphHeight; + } + + if (aa.height == 0) + { + aa.height = 20; + } + + height += aa.height; + } + } + if (height == 0) + { + // set minimum + height = 20; + } + return height; + } + + @Override + public void updateGroupAnnotationSettings(boolean applyGlobalSettings, + boolean preserveNewGroupSettings) + { + boolean updateCalcs = false; + boolean conv = isShowGroupConservation(); + boolean cons = isShowGroupConsensus(); + boolean showprf = isShowSequenceLogo(); + boolean showConsHist = isShowConsensusHistogram(); + boolean normLogo = isNormaliseSequenceLogo(); + + /** + * TODO reorder the annotation rows according to group/sequence ordering on + * alignment + */ + boolean sortg = true; + + // remove old automatic annotation + // add any new annotation + + // intersect alignment annotation with alignment groups + + AlignmentAnnotation[] aan = alignment.getAlignmentAnnotation(); + List oldrfs = new ArrayList(); + if (aan != null) + { + for (int an = 0; an < aan.length; an++) + { + if (aan[an].autoCalculated && aan[an].groupRef != null) + { + oldrfs.add(aan[an].groupRef); + alignment.deleteAnnotation(aan[an], false); + } + } + } + if (alignment.getGroups() != null) { - if (b) + for (SequenceGroup sg : alignment.getGroups()) { - colselhash = hc; + updateCalcs = false; + if (applyGlobalSettings + || (!preserveNewGroupSettings && !oldrfs.contains(sg))) + { + // set defaults for this group's conservation/consensus + sg.setshowSequenceLogo(showprf); + sg.setShowConsensusHistogram(showConsHist); + sg.setNormaliseSequenceLogo(normLogo); + } + if (conv) + { + updateCalcs = true; + alignment.addAnnotation(sg.getConservationRow(), 0); + } + if (cons) + { + updateCalcs = true; + alignment.addAnnotation(sg.getConsensus(), 0); + } + // refresh the annotation rows + if (updateCalcs) + { + sg.recalcConservation(); + } } - return true; } - return false; + oldrfs.clear(); } @Override - public boolean getIgnoreGapsConsensus() - { - return ignoreGapsInConsensusCalculation; - } - - // / property change stuff - - // JBPNote Prolly only need this in the applet version. - private final java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport( - this); - - protected boolean showConservation = true; - - protected boolean showQuality = true; - - protected boolean showConsensus = true; - - Hashtable sequenceColours; - - /** - * Property change listener for changes in alignment - * - * @param listener - * DOCUMENT ME! - */ - public void addPropertyChangeListener( - java.beans.PropertyChangeListener listener) + public boolean isDisplayReferenceSeq() { - changeSupport.addPropertyChangeListener(listener); + return alignment.hasSeqrep() && viewStyle.isDisplayReferenceSeq(); } - /** - * DOCUMENT ME! - * - * @param listener - * DOCUMENT ME! - */ - public void removePropertyChangeListener( - java.beans.PropertyChangeListener listener) + @Override + public void setDisplayReferenceSeq(boolean displayReferenceSeq) { - changeSupport.removePropertyChangeListener(listener); + viewStyle.setDisplayReferenceSeq(displayReferenceSeq); } - /** - * Property change listener for changes in alignment - * - * @param prop - * DOCUMENT ME! - * @param oldvalue - * DOCUMENT ME! - * @param newvalue - * DOCUMENT ME! - */ - public void firePropertyChange(String prop, Object oldvalue, - Object newvalue) + @Override + public boolean isColourByReferenceSeq() { - changeSupport.firePropertyChange(prop, oldvalue, newvalue); + return alignment.hasSeqrep() && viewStyle.isColourByReferenceSeq(); } - // common hide/show column stuff - - public void hideSelectedColumns() + @Override + public Color getSequenceColour(SequenceI seq) { - if (colSel.size() < 1) - { - return; - } - - colSel.hideSelectedColumns(); - setSelectionGroup(null); - - hasHiddenColumns = true; + Color sqc = sequenceColours.get(seq); + return (sqc == null ? Color.white : sqc); } - public void hideColumns(int start, int end) + @Override + public void setSequenceColour(SequenceI seq, Color col) { - if (start == end) + if (col == null) { - colSel.hideColumns(start); + sequenceColours.remove(seq); } else { - colSel.hideColumns(start, end); + sequenceColours.put(seq, col); } - - hasHiddenColumns = true; } - public void showColumn(int col) + @Override + public void updateSequenceIdColours() { - colSel.revealHiddenColumns(col); - if (colSel.getHiddenColumns() == null) + for (SequenceGroup sg : alignment.getGroups()) { - hasHiddenColumns = false; + if (sg.idColour != null) + { + for (SequenceI s : sg.getSequences(getHiddenRepSequences())) + { + sequenceColours.put(s, sg.idColour); + } + } } } - public void showAllHiddenColumns() + @Override + public void clearSequenceColours() { - colSel.revealAllHiddenColumns(); - hasHiddenColumns = false; + sequenceColours.clear(); + }; + + @Override + public AlignViewportI getCodingComplement() + { + return this.codingComplement; } - // common hide/show seq stuff - public void showAllHiddenSeqs() + /** + * Set this as the (cDna/protein) complement of the given viewport. Also + * ensures the reverse relationship is set on the given viewport. + */ + @Override + public void setCodingComplement(AlignViewportI av) { - if (alignment.getHiddenSequences().getSize() > 0) + if (this == av) { - if (selectionGroup == null) - { - selectionGroup = new SequenceGroup(); - selectionGroup.setEndRes(alignment.getWidth() - 1); - } - Vector tmp = alignment.getHiddenSequences().showAll( - hiddenRepSequences); - for (int t = 0; t < tmp.size(); t++) + System.err.println("Ignoring recursive setCodingComplement request"); + } + else + { + this.codingComplement = av; + // avoid infinite recursion! + if (av.getCodingComplement() != this) { - selectionGroup.addSequence((SequenceI) tmp.elementAt(t), false); + av.setCodingComplement(this); } - - hasHiddenRows = false; - hiddenRepSequences = null; - - firePropertyChange("alignment", null, alignment.getSequences()); - // used to set hasHiddenRows/hiddenRepSequences here, after the property - // changed event - sendSelection(); } } - public void showSequence(int index) + @Override + public boolean isNucleotide() { - Vector tmp = alignment.getHiddenSequences().showSequence(index, - hiddenRepSequences); - if (tmp.size() > 0) - { - if (selectionGroup == null) - { - selectionGroup = new SequenceGroup(); - selectionGroup.setEndRes(alignment.getWidth() - 1); - } + return getAlignment() == null ? false : getAlignment().isNucleotide(); + } - for (int t = 0; t < tmp.size(); t++) - { - selectionGroup.addSequence((SequenceI) tmp.elementAt(t), false); - } - // JBPNote: refactor: only update flag if we modified visiblity (used to - // do this regardless) - if (alignment.getHiddenSequences().getSize() < 1) - { - hasHiddenRows = false; - } - firePropertyChange("alignment", null, alignment.getSequences()); - sendSelection(); - } + @Override + public FeaturesDisplayedI getFeaturesDisplayed() + { + return featuresDisplayed; } - public void hideAllSelectedSeqs() + @Override + public void setFeaturesDisplayed(FeaturesDisplayedI featuresDisplayedI) { - if (selectionGroup == null || selectionGroup.getSize() < 1) - { - return; - } + featuresDisplayed = featuresDisplayedI; + } - SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment); + @Override + public boolean areFeaturesDisplayed() + { + return featuresDisplayed != null + && featuresDisplayed.getRegisterdFeaturesCount() > 0; + } - hideSequence(seqs); + /** + * set the flag + * + * @param b + * features are displayed if true + */ + @Override + public void setShowSequenceFeatures(boolean b) + { + viewStyle.setShowSequenceFeatures(b); + } - setSelectionGroup(null); + @Override + public boolean isShowSequenceFeatures() + { + return viewStyle.isShowSequenceFeatures(); } - public void hideSequence(SequenceI[] seq) + @Override + public void setShowSequenceFeaturesHeight(boolean selected) { - if (seq != null) - { - for (int i = 0; i < seq.length; i++) - { - alignment.getHiddenSequences().hideSequence(seq[i]); - } - hasHiddenRows = true; - firePropertyChange("alignment", null, alignment.getSequences()); - } + viewStyle.setShowSequenceFeaturesHeight(selected); } - public void hideRepSequences(SequenceI repSequence, SequenceGroup sg) + @Override + public boolean isShowSequenceFeaturesHeight() { - int sSize = sg.getSize(); - if (sSize < 2) - { - return; - } + return viewStyle.isShowSequenceFeaturesHeight(); + } - if (hiddenRepSequences == null) - { - hiddenRepSequences = new Hashtable(); - } + @Override + public void setShowAnnotation(boolean b) + { + viewStyle.setShowAnnotation(b); + } - hiddenRepSequences.put(repSequence, sg); + @Override + public boolean isShowAnnotation() + { + return viewStyle.isShowAnnotation(); + } - // Hide all sequences except the repSequence - SequenceI[] seqs = new SequenceI[sSize - 1]; - int index = 0; - for (int i = 0; i < sSize; i++) - { - if (sg.getSequenceAt(i) != repSequence) - { - if (index == sSize - 1) - { - return; - } + @Override + public boolean isRightAlignIds() + { + return viewStyle.isRightAlignIds(); + } - seqs[index++] = sg.getSequenceAt(i); - } - } - sg.setSeqrep(repSequence); // note: not done in 2.7applet - sg.setHidereps(true); // note: not done in 2.7applet - hideSequence(seqs); + @Override + public void setRightAlignIds(boolean rightAlignIds) + { + viewStyle.setRightAlignIds(rightAlignIds); + } + @Override + public boolean getConservationSelected() + { + return viewStyle.getConservationSelected(); } - public boolean isHiddenRepSequence(SequenceI seq) + @Override + public void setShowBoxes(boolean state) { - return hiddenRepSequences != null - && hiddenRepSequences.containsKey(seq); + viewStyle.setShowBoxes(state); } - public SequenceGroup getRepresentedSequences(SequenceI seq) + /** + * @return + * @see jalview.api.ViewStyleI#getTextColour() + */ + public Color getTextColour() { - return (SequenceGroup) (hiddenRepSequences == null ? null - : hiddenRepSequences.get(seq)); + return viewStyle.getTextColour(); } - public int adjustForHiddenSeqs(int alignmentIndex) + /** + * @return + * @see jalview.api.ViewStyleI#getTextColour2() + */ + public Color getTextColour2() { - return alignment.getHiddenSequences().adjustForHiddenSeqs( - alignmentIndex); + return viewStyle.getTextColour2(); } - // Selection manipulation /** - * broadcast selection to any interested parties + * @return + * @see jalview.api.ViewStyleI#getThresholdTextColour() */ - public abstract void sendSelection(); - - public void invertColumnSelection() + public int getThresholdTextColour() { - colSel.invertColumnSelection(0, alignment.getWidth()); + return viewStyle.getThresholdTextColour(); } /** - * This method returns an array of new SequenceI objects derived from the - * whole alignment or just the current selection with start and end points - * adjusted - * - * @note if you need references to the actual SequenceI objects in the - * alignment or currently selected then use getSequenceSelection() - * @return selection as new sequenceI objects + * @return + * @see jalview.api.ViewStyleI#isConservationColourSelected() */ - public SequenceI[] getSelectionAsNewSequence() + public boolean isConservationColourSelected() { - SequenceI[] sequences; - // JBPNote: Need to test jalviewLite.getSelectedSequencesAsAlignmentFrom - - // this was the only caller in the applet for this method - // JBPNote: in applet, this method returned references to the alignment - // sequences, and it did not honour the presence/absence of annotation - // attached to the alignment (probably!) - if (selectionGroup == null || selectionGroup.getSize() == 0) - { - sequences = alignment.getSequencesArray(); - AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation(); - for (int i = 0; i < sequences.length; i++) - { - sequences[i] = new Sequence(sequences[i], annots); // construct new - // sequence with - // subset of visible - // annotation - } - } - else - { - sequences = selectionGroup.getSelectionAsNewSequences(alignment); - } - - return sequences; + return viewStyle.isConservationColourSelected(); } /** - * get the currently selected sequence objects or all the sequences in the - * alignment. - * - * @return array of references to sequence objects + * @return + * @see jalview.api.ViewStyleI#isRenderGaps() */ - @Override - public SequenceI[] getSequenceSelection() + public boolean isRenderGaps() { - SequenceI[] sequences = null; - if (selectionGroup != null) - { - sequences = selectionGroup.getSequencesInOrder(alignment); - } - if (sequences == null) - { - sequences = alignment.getSequencesArray(); - } - return sequences; + return viewStyle.isRenderGaps(); } /** - * This method returns the visible alignment as text, as seen on the GUI, ie - * if columns are hidden they will not be returned in the result. Use this for - * calculating trees, PCA, redundancy etc on views which contain hidden - * columns. - * - * @return String[] + * @return + * @see jalview.api.ViewStyleI#isShowColourText() */ - @Override - public jalview.datamodel.CigarArray getViewAsCigars( - boolean selectedRegionOnly) + public boolean isShowColourText() { - return new jalview.datamodel.CigarArray(alignment, - (hasHiddenColumns ? colSel : null), - (selectedRegionOnly ? selectionGroup : null)); + return viewStyle.isShowColourText(); } /** - * return a compact representation of the current alignment selection to pass - * to an analysis function - * - * @param selectedOnly - * boolean true to just return the selected view - * @return AlignmentView + * @param conservationColourSelected + * @see jalview.api.ViewStyleI#setConservationColourSelected(boolean) */ - @Override - public jalview.datamodel.AlignmentView getAlignmentView( - boolean selectedOnly) + public void setConservationColourSelected( + boolean conservationColourSelected) { - return getAlignmentView(selectedOnly, false); + viewStyle.setConservationColourSelected(conservationColourSelected); } /** - * return a compact representation of the current alignment selection to pass - * to an analysis function - * - * @param selectedOnly - * boolean true to just return the selected view - * @param markGroups - * boolean true to annotate the alignment view with groups on the - * alignment (and intersecting with selected region if selectedOnly - * is true) - * @return AlignmentView + * @param showColourText + * @see jalview.api.ViewStyleI#setShowColourText(boolean) */ - @Override - public jalview.datamodel.AlignmentView getAlignmentView( - boolean selectedOnly, boolean markGroups) + public void setShowColourText(boolean showColourText) { - return new AlignmentView(alignment, colSel, selectionGroup, - hasHiddenColumns, selectedOnly, markGroups); + viewStyle.setShowColourText(showColourText); } /** - * This method returns the visible alignment as text, as seen on the GUI, ie - * if columns are hidden they will not be returned in the result. Use this for - * calculating trees, PCA, redundancy etc on views which contain hidden - * columns. - * - * @return String[] + * @param textColour + * @see jalview.api.ViewStyleI#setTextColour(java.awt.Color) */ - @Override - public String[] getViewAsString(boolean selectedRegionOnly) + public void setTextColour(Color textColour) { - String[] selection = null; - SequenceI[] seqs = null; - int i, iSize; - int start = 0, end = 0; - if (selectedRegionOnly && selectionGroup != null) - { - iSize = selectionGroup.getSize(); - seqs = selectionGroup.getSequencesInOrder(alignment); - start = selectionGroup.getStartRes(); - end = selectionGroup.getEndRes() + 1; - } - else - { - iSize = alignment.getHeight(); - seqs = alignment.getSequencesArray(); - end = alignment.getWidth(); - } - - selection = new String[iSize]; - if (hasHiddenColumns) - { - selection = colSel.getVisibleSequenceStrings(start, end, seqs); - } - else - { - for (i = 0; i < iSize; i++) - { - selection[i] = seqs[i].getSequenceAsString(start, end); - } - - } - return selection; + viewStyle.setTextColour(textColour); } /** - * return visible region boundaries within given column range - * - * @param min - * first column (inclusive, from 0) - * @param max - * last column (exclusive) - * @return int[][] range of {start,end} visible positions + * @param thresholdTextColour + * @see jalview.api.ViewStyleI#setThresholdTextColour(int) */ - public int[][] getVisibleRegionBoundaries(int min, int max) + public void setThresholdTextColour(int thresholdTextColour) { - Vector regions = new Vector(); - int start = min; - int end = max; - - do - { - if (hasHiddenColumns) - { - if (start == 0) - { - start = colSel.adjustForHiddenColumns(start); - } - - end = colSel.getHiddenBoundaryRight(start); - if (start == end) - { - end = max; - } - if (end > max) - { - end = max; - } - } - - regions.addElement(new int[] - { start, end }); - - if (hasHiddenColumns) - { - start = colSel.adjustForHiddenColumns(end); - start = colSel.getHiddenBoundaryLeft(start) + 1; - } - } while (end < max); + viewStyle.setThresholdTextColour(thresholdTextColour); + } - int[][] startEnd = new int[regions.size()][2]; + /** + * @param textColour2 + * @see jalview.api.ViewStyleI#setTextColour2(java.awt.Color) + */ + public void setTextColour2(Color textColour2) + { + viewStyle.setTextColour2(textColour2); + } - regions.copyInto(startEnd); + @Override + public ViewStyleI getViewStyle() + { + return new ViewStyle(viewStyle); + } - return startEnd; + @Override + public void setViewStyle(ViewStyleI settingsForView) + { + viewStyle = new ViewStyle(settingsForView); + } + @Override + public boolean sameStyle(ViewStyleI them) + { + return viewStyle.sameStyle(them); } /** - * @return the padGaps + * @return + * @see jalview.api.ViewStyleI#getIdWidth() */ - public boolean isPadGaps() + public int getIdWidth() { - return padGaps; + return viewStyle.getIdWidth(); } /** - * @param padGaps - * the padGaps to set + * @param i + * @see jalview.api.ViewStyleI#setIdWidth(int) */ - public void setPadGaps(boolean padGaps) + public void setIdWidth(int i) { - this.padGaps = padGaps; + viewStyle.setIdWidth(i); } /** - * apply any post-edit constraints and trigger any calculations needed after - * an edit has been performed on the alignment - * - * @param ap + * @return + * @see jalview.api.ViewStyleI#isCentreColumnLabels() */ - public void alignmentChanged(AlignmentViewPanel ap) + public boolean isCentreColumnLabels() { - if (isPadGaps()) - { - alignment.padGaps(); - } - if (autoCalculateConsensus) - { - updateConsensus(ap); - } - if (hconsensus != null && autoCalculateConsensus) - { - updateConservation(ap); - } - if (autoCalculateStrucConsensus) - { - updateStrucConsensus(ap); - } - - // Reset endRes of groups if beyond alignment width - int alWidth = alignment.getWidth(); - List groups = alignment.getGroups(); - if (groups != null) - { - for (SequenceGroup sg : groups) - { - if (sg.getEndRes() > alWidth) - { - sg.setEndRes(alWidth - 1); - } - } - } - - if (selectionGroup != null && selectionGroup.getEndRes() > alWidth) - { - selectionGroup.setEndRes(alWidth - 1); - } - - resetAllColourSchemes(); - calculator.restartWorkers(); - // alignment.adjustSequenceAnnotations(); + return viewStyle.isCentreColumnLabels(); } /** - * reset scope and do calculations for all applied colourschemes on alignment + * @param centreColumnLabels + * @see jalview.api.ViewStyleI#setCentreColumnLabels(boolean) */ - void resetAllColourSchemes() + public void setCentreColumnLabels(boolean centreColumnLabels) { - ColourSchemeI cs = globalColourScheme; - if (cs != null) - { - cs.alignmentChanged(alignment, hiddenRepSequences); - - cs.setConsensus(hconsensus); - if (cs.conservationApplied()) - { - cs.setConservation(Conservation.calculateConservation("All", - ResidueProperties.propHash, 3, alignment.getSequences(), 0, - alignment.getWidth(), false, getConsPercGaps(), false)); - } - } + viewStyle.setCentreColumnLabels(centreColumnLabels); + } - for (SequenceGroup sg : alignment.getGroups()) - { - if (sg.cs != null) - { - sg.cs.alignmentChanged(sg, hiddenRepSequences); - } - sg.recalcConservation(); - } + /** + * @param showdbrefs + * @see jalview.api.ViewStyleI#setShowDBRefs(boolean) + */ + public void setShowDBRefs(boolean showdbrefs) + { + viewStyle.setShowDBRefs(showdbrefs); } - protected void initAutoAnnotation() + /** + * @return + * @see jalview.api.ViewStyleI#isShowDBRefs() + */ + public boolean isShowDBRefs() { - // TODO: add menu option action that nulls or creates consensus object - // depending on if the user wants to see the annotation or not in a - // specific alignment + return viewStyle.isShowDBRefs(); + } - if (hconsensus == null && !isDataset) - { - if (!alignment.isNucleotide()) - { - initConservation(); - initQuality(); - } - else - { - initRNAStructure(); - } - initConsensus(); - } + /** + * @return + * @see jalview.api.ViewStyleI#isShowNPFeats() + */ + public boolean isShowNPFeats() + { + return viewStyle.isShowNPFeats(); } - private void initConsensus() + /** + * @param shownpfeats + * @see jalview.api.ViewStyleI#setShowNPFeats(boolean) + */ + public void setShowNPFeats(boolean shownpfeats) { + viewStyle.setShowNPFeats(shownpfeats); + } - consensus = new AlignmentAnnotation("Consensus", "PID", - new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); - consensus.hasText = true; - consensus.autoCalculated = true; + public abstract StructureSelectionManager getStructureSelectionManager(); - if (showConsensus) + /** + * Add one command to the command history list. + * + * @param command + */ + public void addToHistoryList(CommandI command) + { + if (this.historyList != null) { - alignment.addAnnotation(consensus); + this.historyList.push(command); + broadcastCommand(command, false); } } - private void initConservation() + protected void broadcastCommand(CommandI command, boolean undo) { - if (showConservation) - { - if (conservation == null) - { - conservation = new AlignmentAnnotation("Conservation", - "Conservation of total alignment less than " - + getConsPercGaps() + "% gaps", new Annotation[1], - 0f, 11f, AlignmentAnnotation.BAR_GRAPH); - conservation.hasText = true; - conservation.autoCalculated = true; - alignment.addAnnotation(conservation); - } - } + getStructureSelectionManager().commandPerformed(command, undo, + getVamsasSource()); } - private void initQuality() + /** + * Add one command to the command redo list. + * + * @param command + */ + public void addToRedoList(CommandI command) { - if (showQuality) + if (this.redoList != null) { - if (quality == null) - { - quality = new AlignmentAnnotation("Quality", - "Alignment Quality based on Blosum62 scores", - new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH); - quality.hasText = true; - quality.autoCalculated = true; - alignment.addAnnotation(quality); - } + this.redoList.push(command); } + broadcastCommand(command, true); } - private void initRNAStructure() + /** + * Clear the command redo list. + */ + public void clearRedoList() { - if (alignment.hasRNAStructure() && strucConsensus == null) + if (this.redoList != null) { - strucConsensus = new AlignmentAnnotation("StrucConsensus", "PID", - new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); - strucConsensus.hasText = true; - strucConsensus.autoCalculated = true; - - if (showConsensus) - { - alignment.addAnnotation(strucConsensus); - } + this.redoList.clear(); } } - /* - * (non-Javadoc) - * - * @see jalview.api.AlignViewportI#calcPanelHeight() - */ - public int calcPanelHeight() + public void setHistoryList(Deque list) { - // setHeight of panels - AlignmentAnnotation[] aa = getAlignment().getAlignmentAnnotation(); - int height = 0; - int charHeight = getCharHeight(); - if (aa != null) - { - BitSet graphgrp = new BitSet(); - for (int i = 0; i < aa.length; i++) - { - if (aa[i] == null) - { - System.err.println("Null annotation row: ignoring."); - continue; - } - if (!aa[i].visible) - { - continue; - } - if (aa[i].graphGroup > -1) - { - if (graphgrp.get(aa[i].graphGroup)) - { - continue; - } - else - { - graphgrp.set(aa[i].graphGroup); - } - } - aa[i].height = 0; - - if (aa[i].hasText) - { - aa[i].height += charHeight; - } - - if (aa[i].hasIcons) - { - aa[i].height += 16; - } + this.historyList = list; + } - if (aa[i].graph > 0) - { - aa[i].height += aa[i].graphHeight; - } + public Deque getHistoryList() + { + return this.historyList; + } - if (aa[i].height == 0) - { - aa[i].height = 20; - } + public void setRedoList(Deque list) + { + this.redoList = list; + } - height += aa[i].height; - } - } - if (height == 0) - { - // set minimum - height = 20; - } - return height; + public Deque getRedoList() + { + return this.redoList; } @Override - public void updateGroupAnnotationSettings(boolean applyGlobalSettings, - boolean preserveNewGroupSettings) + public VamsasSource getVamsasSource() { - boolean updateCalcs = false; - boolean conv = isShowGroupConservation(); - boolean cons = isShowGroupConsensus(); - boolean showprf = isShowSequenceLogo(); - boolean showConsHist = isShowConsensusHistogram(); - boolean normLogo = isNormaliseSequenceLogo(); - - /** - * TODO reorder the annotation rows according to group/sequence ordering on - * alignment - */ - boolean sortg = true; + return this; + } - // remove old automatic annotation - // add any new annotation + public SequenceAnnotationOrder getSortAnnotationsBy() + { + return sortAnnotationsBy; + } - // intersect alignment annotation with alignment groups + public void setSortAnnotationsBy(SequenceAnnotationOrder sortAnnotationsBy) + { + this.sortAnnotationsBy = sortAnnotationsBy; + } - AlignmentAnnotation[] aan = alignment.getAlignmentAnnotation(); - List oldrfs = new ArrayList(); - if (aan != null) - { - for (int an = 0; an < aan.length; an++) - { - if (aan[an].autoCalculated && aan[an].groupRef != null) - { - oldrfs.add(aan[an].groupRef); - alignment.deleteAnnotation(aan[an], false); - } - } - } - if (alignment.getGroups() != null) - { - for (SequenceGroup sg : alignment.getGroups()) - { - updateCalcs = false; - if (applyGlobalSettings - || (!preserveNewGroupSettings && !oldrfs.contains(sg))) - { - // set defaults for this group's conservation/consensus - sg.setshowSequenceLogo(showprf); - sg.setShowConsensusHistogram(showConsHist); - sg.setNormaliseSequenceLogo(normLogo); - } - if (conv) - { - updateCalcs = true; - alignment.addAnnotation(sg.getConservationRow(), 0); - } - if (cons) - { - updateCalcs = true; - alignment.addAnnotation(sg.getConsensus(), 0); - } - // refresh the annotation rows - if (updateCalcs) - { - sg.recalcConservation(); - } - } - } - oldrfs.clear(); + public boolean isShowAutocalculatedAbove() + { + return showAutocalculatedAbove; } - @Override - public Color getSequenceColour(SequenceI seq) + public void setShowAutocalculatedAbove(boolean showAutocalculatedAbove) { - Color sqc = Color.white; - if (sequenceColours != null) - { - sqc = (Color) sequenceColours.get(seq); - if (sqc == null) - { - sqc = Color.white; - } - } - return sqc; + this.showAutocalculatedAbove = showAutocalculatedAbove; } @Override - public void setSequenceColour(SequenceI seq, Color col) + public boolean isScaleProteinAsCdna() { - if (sequenceColours == null) - { - sequenceColours = new Hashtable(); - } - - if (col == null) - { - sequenceColours.remove(seq); - } - else - { - sequenceColours.put(seq, col); - } + return viewStyle.isScaleProteinAsCdna(); } @Override - public void updateSequenceIdColours() + public void setScaleProteinAsCdna(boolean b) { - if (sequenceColours == null) - { - sequenceColours = new Hashtable(); - } - for (SequenceGroup sg : alignment.getGroups()) - { - if (sg.idColour != null) - { - for (SequenceI s : sg.getSequences(getHiddenRepSequences())) - { - sequenceColours.put(s, sg.idColour); - } - } - } + viewStyle.setScaleProteinAsCdna(b); } + /** + * @return true if view should scroll to show the highlighted region of a + * sequence + * @return + */ @Override - public void clearSequenceColours() + public final boolean isFollowHighlight() { - sequenceColours = null; - }; - - FeaturesDisplayedI featuresDisplayed = null; + return followHighlight; + } @Override - public FeaturesDisplayedI getFeaturesDisplayed() + public final void setFollowHighlight(boolean b) { - return featuresDisplayed; + this.followHighlight = b; } - public void setFeaturesDisplayed(FeaturesDisplayedI featuresDisplayedI) + public int getStartRes() { - featuresDisplayed = featuresDisplayedI; + return startRes; } - public boolean areFeaturesDisplayed() + public int getEndRes() { - return featuresDisplayed != null && featuresDisplayed.getRegisterdFeaturesCount()>0; + return endRes; } - /** - * display setting for showing/hiding sequence features on alignment view - */ - boolean showSequenceFeatures = false; + public int getStartSeq() + { + return startSeq; + } - /** - * set the flag - * - * @param b - * features are displayed if true - */ - @Override - public void setShowSequenceFeatures(boolean b) + public void setStartRes(int res) { - showSequenceFeatures = b; + this.startRes = res; } - @Override - public boolean isShowSequenceFeatures() + + public void setStartSeq(int seq) { - return showSequenceFeatures; + this.startSeq = seq; } - boolean showSeqFeaturesHeight; + public void setEndRes(int res) + { + if (res > alignment.getWidth() - 1) + { + // log.System.out.println(" Corrected res from " + res + " to maximum " + + // (alignment.getWidth()-1)); + res = alignment.getWidth() - 1; + } + if (res < 0) + { + res = 0; + } + this.endRes = res; + } - public void setShowSequenceFeaturesHeight(boolean selected) + public void setEndSeq(int seq) { - showSeqFeaturesHeight = selected; + if (seq > alignment.getHeight()) + { + seq = alignment.getHeight(); + } + if (seq < 0) + { + seq = 0; + } + this.endSeq = seq; } - public boolean isShowSequenceFeaturesHeight() + public int getEndSeq() { - return showSeqFeaturesHeight; + return endSeq; } + /** + * Helper method to populate the SearchResults with the location in the + * complementary alignment to scroll to, in order to match this one. + * + * @param sr + * the SearchResults to add to + * @return the offset (below top of visible region) of the matched sequence + */ + protected int findComplementScrollTarget(SearchResults sr) + { + final AlignViewportI complement = getCodingComplement(); + if (complement == null || !complement.isFollowHighlight()) + { + return 0; + } + boolean iAmProtein = !getAlignment().isNucleotide(); + AlignmentI proteinAlignment = iAmProtein ? getAlignment() : complement + .getAlignment(); + if (proteinAlignment == null) + { + return 0; + } + final Set mappings = proteinAlignment + .getCodonFrames(); + + /* + * Heuristic: find the first mapped sequence (if any) with a non-gapped + * residue in the middle column of the visible region. Scroll the + * complementary alignment to line up the corresponding residue. + */ + int seqOffset = 0; + SequenceI sequence = null; + + /* + * locate 'middle' column (true middle if an odd number visible, left of + * middle if an even number visible) + */ + int middleColumn = getStartRes() + (getEndRes() - getStartRes()) / 2; + final HiddenSequences hiddenSequences = getAlignment() + .getHiddenSequences(); + + /* + * searching to the bottom of the alignment gives smoother scrolling across + * all gapped visible regions + */ + int lastSeq = alignment.getHeight() - 1; + for (int seqNo = getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++) + { + sequence = getAlignment().getSequenceAt(seqNo); + if (hiddenSequences != null && hiddenSequences.isHidden(sequence)) + { + continue; + } + if (Comparison.isGap(sequence.getCharAt(middleColumn))) + { + continue; + } + List seqMappings = MappingUtils + .findMappingsForSequence(sequence, mappings); + if (!seqMappings.isEmpty()) + { + break; + } + } + if (sequence == null) + { + /* + * No ungapped mapped sequence in middle column - do nothing + */ + return 0; + } + MappingUtils.addSearchResults(sr, sequence, + sequence.findPosition(middleColumn), mappings); + return seqOffset; + } }