/*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
- * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.viewmodel;
-import jalview.analysis.AAFrequency;
+import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.analysis.Conservation;
-import jalview.api.AlignCalcManagerI;
+import jalview.analysis.TreeModel;
+import jalview.api.AlignCalcManagerI2;
+import jalview.api.AlignCalcWorkerI;
+import jalview.api.AlignExportSettingsI;
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.AlignmentExportData;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.Annotation;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenSequences;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.SearchResultsI;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
-import jalview.schemes.Blosum62ColourScheme;
-import jalview.schemes.ClustalxColourScheme;
+import jalview.renderer.ResidueShader;
+import jalview.renderer.ResidueShaderI;
import jalview.schemes.ColourSchemeI;
-import jalview.schemes.PIDColourScheme;
-import jalview.schemes.ResidueProperties;
-import jalview.workers.AlignCalcManager;
+import jalview.structure.CommandListener;
+import jalview.structure.StructureSelectionManager;
+import jalview.structure.VamsasSource;
+import jalview.util.Comparison;
+import jalview.util.MapList;
+import jalview.util.MappingUtils;
+import jalview.util.MessageManager;
+import jalview.viewmodel.styles.ViewStyle;
+import jalview.workers.AlignCalcManager2;
+import jalview.workers.ComplementConsensusThread;
import jalview.workers.ConsensusThread;
+import jalview.workers.InformationThread;
import jalview.workers.StrucConsensusThread;
+import java.awt.Color;
+import java.beans.PropertyChangeSupport;
+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.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Vector;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
/**
* base class holding visualization and analysis attributes and common logic for
* @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;
+ public static final String PROPERTY_ALIGNMENT = "alignment";
+ public static final String PROPERTY_SEQUENCE = "sequence";
+ protected ViewportRanges ranges;
- 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<SequenceI, SequenceCollectionI> hiddenRepSequences;
+ FeaturesDisplayedI featuresDisplayed = null;
- protected ColumnSelection colSel = new ColumnSelection();
+ protected Deque<CommandI> historyList = new ArrayDeque<>();
- public boolean autoCalculateConsensus = true;
+ protected Deque<CommandI> redoList = new ArrayDeque<>();
- protected boolean autoCalculateStrucConsensus = true;
+ /**
+ * alignment displayed in the viewport. Please use get/setter
+ */
+ protected AlignmentI alignment;
+
+ /*
+ * probably unused indicator that view is of a dataset rather than an
+ * alignment
+ */
- protected boolean ignoreGapsInConsensusCalculation = false;
+ protected boolean ignoreBelowBackGroundFrequencyCalculation = false;
- protected ColourSchemeI globalColourScheme = null;
+ protected boolean infoLetterHeight = false;
+ protected AlignmentAnnotation occupancy;
+
/**
- * gui state - changes to colour scheme propagated to all groups
+ * results of alignment consensus analysis for visible portion of view
*/
- private boolean colourAppliesToAllGroups;
+ protected ProfilesI consensusProfiles;
/**
- * @param value
- * indicating if subsequent colourscheme changes will be propagated
- * to all groups
+ * HMM profile for the alignment
*/
- public void setColourAppliesToAllGroups(boolean b)
+ protected ProfilesI hmmProfiles;
+
+ public AlignmentViewport(AlignmentI al)
{
- colourAppliesToAllGroups = b;
+ setAlignment(al);
+ ranges = new ViewportRanges(al);
}
/**
- *
- *
- * @return flag indicating if colourchanges propagated to all groups
+ * @param name
+ * @see jalview.api.ViewStyleI#setFontName(java.lang.String)
*/
- public boolean getColourAppliesToAllGroups()
+ @Override
+ public void setFontName(String name)
{
- return colourAppliesToAllGroups;
+ viewStyle.setFontName(name);
}
- boolean abovePIDThreshold = false;
-
/**
- * GUI state
- *
- * @return true if percent identity threshold is applied to shading
+ * @param style
+ * @see jalview.api.ViewStyleI#setFontStyle(int)
*/
- public boolean getAbovePIDThreshold()
+ @Override
+ public void setFontStyle(int style)
{
- return abovePIDThreshold;
+ viewStyle.setFontStyle(style);
}
/**
- * GUI state
- *
- *
- * @param b
- * indicate if percent identity threshold is applied to shading
+ * @param size
+ * @see jalview.api.ViewStyleI#setFontSize(int)
*/
- public void setAbovePIDThreshold(boolean b)
+ @Override
+ public void setFontSize(int size)
{
- abovePIDThreshold = b;
+ viewStyle.setFontSize(size);
}
- int threshold;
-
/**
- * DOCUMENT ME!
- *
- * @param thresh
- * DOCUMENT ME!
+ * @return
+ * @see jalview.api.ViewStyleI#getFontStyle()
*/
- public void setThreshold(int thresh)
+ @Override
+ public int getFontStyle()
{
- threshold = thresh;
+ return viewStyle.getFontStyle();
}
/**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
+ * @return
+ * @see jalview.api.ViewStyleI#getFontName()
*/
- public int getThreshold()
+ @Override
+ public String getFontName()
{
- return threshold;
+ return viewStyle.getFontName();
}
- int increment;
-
/**
- *
- * @param inc
- * set the scalar for bleaching colourschemes according to degree of
- * conservation
+ * @return
+ * @see jalview.api.ViewStyleI#getFontSize()
*/
- public void setIncrement(int inc)
+ @Override
+ public int getFontSize()
{
- increment = inc;
+ return viewStyle.getFontSize();
}
/**
- * GUI State
- *
- * @return get scalar for bleaching colourschemes by conservation
+ * @param upperCasebold
+ * @see jalview.api.ViewStyleI#setUpperCasebold(boolean)
*/
- public int getIncrement()
+ @Override
+ public void setUpperCasebold(boolean upperCasebold)
{
- return increment;
+ viewStyle.setUpperCasebold(upperCasebold);
}
- boolean conservationColourSelected = false;
-
/**
- * GUI state
- *
- * @return true if conservation based shading is enabled
+ * @return
+ * @see jalview.api.ViewStyleI#isUpperCasebold()
*/
- public boolean getConservationSelected()
+ @Override
+ public boolean isUpperCasebold()
{
- return conservationColourSelected;
+ return viewStyle.isUpperCasebold();
}
/**
- * GUI state
- *
- * @param b
- * enable conservation based shading
+ * @return
+ * @see jalview.api.ViewStyleI#isSeqNameItalics()
*/
- public void setConservationSelected(boolean b)
+ @Override
+ public boolean isSeqNameItalics()
{
- conservationColourSelected = b;
+ return viewStyle.isSeqNameItalics();
}
+ /**
+ * @param colourByReferenceSeq
+ * @see jalview.api.ViewStyleI#setColourByReferenceSeq(boolean)
+ */
@Override
- public void setGlobalColourScheme(ColourSchemeI cs)
+ public void setColourByReferenceSeq(boolean colourByReferenceSeq)
{
- // 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;
- if (getColourAppliesToAllGroups())
- {
- for (SequenceGroup sg : getAlignment().getGroups())
- {
- if (cs == null)
- {
- sg.cs = null;
- continue;
- }
- if (cs instanceof ClustalxColourScheme)
- {
- sg.cs = new ClustalxColourScheme(sg, getHiddenRepSequences());
- }
- else
- {
- try
- {
- sg.cs = cs.getClass().newInstance();
- } catch (Exception ex)
- {
- ex.printStackTrace();
- sg.cs = cs;
- }
- }
-
- if (getAbovePIDThreshold() || cs instanceof PIDColourScheme
- || cs instanceof Blosum62ColourScheme)
- {
- sg.cs.setThreshold(threshold, getIgnoreGapsConsensus());
- sg.cs.setConsensus(AAFrequency.calculate(
- sg.getSequences(getHiddenRepSequences()), 0,
- sg.getWidth()));
- }
- else
- {
- sg.cs.setThreshold(0, getIgnoreGapsConsensus());
- }
-
- if (getConservationSelected())
- {
- Conservation c = new Conservation("Group",
- ResidueProperties.propHash, 3,
- sg.getSequences(getHiddenRepSequences()), 0,
- getAlignment().getWidth() - 1);
- c.calculate();
- c.verdict(false, getConsPercGaps());
- sg.cs.setConservation(c);
- }
- else
- {
- sg.cs.setConservation(null);
- sg.cs.setThreshold(0, getIgnoreGapsConsensus());
- }
-
- }
- }
-
+ viewStyle.setColourByReferenceSeq(colourByReferenceSeq);
}
+ /**
+ * @param b
+ * @see jalview.api.ViewStyleI#setColourAppliesToAllGroups(boolean)
+ */
@Override
- public ColourSchemeI getGlobalColourScheme()
+ public void setColourAppliesToAllGroups(boolean b)
{
- return globalColourScheme;
+ viewStyle.setColourAppliesToAllGroups(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
+ * @return
+ * @see jalview.api.ViewStyleI#getColourAppliesToAllGroups()
*/
- protected Hashtable[] hconsensus = null;
+ @Override
+ public boolean getColourAppliesToAllGroups()
+ {
+ return viewStyle.getColourAppliesToAllGroups();
+ }
/**
- * results of secondary structure base pair consensus for visible portion of
- * view
+ * @return
+ * @see jalview.api.ViewStyleI#getAbovePIDThreshold()
*/
- protected Hashtable[] hStrucConsensus = null;
+ @Override
+ public boolean getAbovePIDThreshold()
+ {
+ return viewStyle.getAbovePIDThreshold();
+ }
/**
- * percentage gaps allowed in a column before all amino acid properties should
- * be considered unconserved
+ * @param inc
+ * @see jalview.api.ViewStyleI#setIncrement(int)
*/
- int ConsPercGaps = 25; // JBPNote : This should be a scalable property!
-
@Override
- public int getConsPercGaps()
+ public void setIncrement(int inc)
{
- return ConsPercGaps;
+ viewStyle.setIncrement(inc);
}
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getIncrement()
+ */
@Override
- public void setSequenceConsensusHash(Hashtable[] hconsensus)
+ public int getIncrement()
{
- this.hconsensus = hconsensus;
-
+ return viewStyle.getIncrement();
}
+ /**
+ * @param b
+ * @see jalview.api.ViewStyleI#setConservationSelected(boolean)
+ */
@Override
- public Hashtable[] getSequenceConsensusHash()
+ public void setConservationSelected(boolean b)
{
- return hconsensus;
+ viewStyle.setConservationSelected(b);
}
+ /**
+ * @param show
+ * @see jalview.api.ViewStyleI#setShowHiddenMarkers(boolean)
+ */
@Override
- public Hashtable[] getRnaStructureConsensusHash()
+ public void setShowHiddenMarkers(boolean show)
{
- return hStrucConsensus;
+ viewStyle.setShowHiddenMarkers(show);
}
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getShowHiddenMarkers()
+ */
@Override
- public void setRnaStructureConsensusHash(Hashtable[] hStrucConsensus)
+ public boolean getShowHiddenMarkers()
{
- this.hStrucConsensus = hStrucConsensus;
-
+ return viewStyle.getShowHiddenMarkers();
}
+ /**
+ * @param b
+ * @see jalview.api.ViewStyleI#setScaleRightWrapped(boolean)
+ */
@Override
- public AlignmentAnnotation getAlignmentQualityAnnot()
+ public void setScaleRightWrapped(boolean b)
{
- return quality;
+ viewStyle.setScaleRightWrapped(b);
}
+ /**
+ * @param b
+ * @see jalview.api.ViewStyleI#setScaleLeftWrapped(boolean)
+ */
@Override
- public AlignmentAnnotation getAlignmentConservationAnnotation()
+ public void setScaleLeftWrapped(boolean b)
{
- return conservation;
+ viewStyle.setScaleLeftWrapped(b);
}
+ /**
+ * @param b
+ * @see jalview.api.ViewStyleI#setScaleAboveWrapped(boolean)
+ */
@Override
- public AlignmentAnnotation getAlignmentConsensusAnnotation()
+ public void setScaleAboveWrapped(boolean b)
{
- return consensus;
+ viewStyle.setScaleAboveWrapped(b);
}
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getScaleLeftWrapped()
+ */
@Override
- public AlignmentAnnotation getAlignmentStrucConsensusAnnotation()
+ public boolean getScaleLeftWrapped()
{
- return strucConsensus;
+ return viewStyle.getScaleLeftWrapped();
}
- protected AlignCalcManagerI calculator = new AlignCalcManager();
-
/**
- * trigger update of conservation annotation
+ * @return
+ * @see jalview.api.ViewStyleI#getScaleAboveWrapped()
*/
- public void updateConservation(final AlignmentViewPanel ap)
+ @Override
+ public boolean getScaleAboveWrapped()
{
- // 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));
- }
+ return viewStyle.getScaleAboveWrapped();
}
/**
- * trigger update of consensus annotation
+ * @return
+ * @see jalview.api.ViewStyleI#getScaleRightWrapped()
*/
- public void updateConsensus(final AlignmentViewPanel ap)
+ @Override
+ public boolean getScaleRightWrapped()
{
- // see note in mantis : issue number 8585
- if (consensus == null || !autoCalculateConsensus)
- {
- return;
- }
- if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null)
- {
- calculator.registerWorker(new ConsensusThread(this, ap));
- }
+ return viewStyle.getScaleRightWrapped();
}
- // --------START Structure Conservation
- public void updateStrucConsensus(final AlignmentViewPanel ap)
+ /**
+ * @param b
+ * @see jalview.api.ViewStyleI#setAbovePIDThreshold(boolean)
+ */
+ @Override
+ public void setAbovePIDThreshold(boolean b)
{
- 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));
- }
+ viewStyle.setAbovePIDThreshold(b);
}
- public boolean isCalcInProgress()
+ /**
+ * @param thresh
+ * @see jalview.api.ViewStyleI#setThreshold(int)
+ */
+ @Override
+ public void setThreshold(int thresh)
{
- return calculator.isWorking();
+ viewStyle.setThreshold(thresh);
}
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getThreshold()
+ */
@Override
- public boolean isCalculationInProgress(
- AlignmentAnnotation alignmentAnnotation)
+ public int getThreshold()
{
- if (!alignmentAnnotation.autoCalculated)
- return false;
- if (calculator.workingInvolvedWith(alignmentAnnotation))
- {
- // System.err.println("grey out ("+alignmentAnnotation.label+")");
- return true;
- }
- return false;
+ return viewStyle.getThreshold();
}
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getShowJVSuffix()
+ */
@Override
- public boolean isClosed()
+ public boolean getShowJVSuffix()
{
- // TODO: check that this isClosed is only true after panel is closed, not
- // before it is fully constructed.
- return alignment == null;
+ return viewStyle.getShowJVSuffix();
}
+ /**
+ * @param b
+ * @see jalview.api.ViewStyleI#setShowJVSuffix(boolean)
+ */
@Override
- public AlignCalcManagerI getCalcManager()
+ public void setShowJVSuffix(boolean b)
{
- return calculator;
+ viewStyle.setShowJVSuffix(b);
}
/**
- * 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
+ * @param state
+ * @see jalview.api.ViewStyleI#setWrapAlignment(boolean)
*/
- protected boolean normaliseSequenceLogo = false;
+ @Override
+ public void setWrapAlignment(boolean state)
+ {
+ viewStyle.setWrapAlignment(state);
+ ranges.setWrappedMode(state);
+ }
/**
- * should consensus histograms be rendered by default
+ * @param state
+ * @see jalview.api.ViewStyleI#setShowText(boolean)
*/
- protected boolean showConsensusHistogram = true;
+ @Override
+ public void setShowText(boolean state)
+ {
+ viewStyle.setShowText(state);
+ }
/**
- * @return the showConsensusProfile
+ * @param state
+ * @see jalview.api.ViewStyleI#setRenderGaps(boolean)
*/
@Override
- public boolean isShowSequenceLogo()
+ public void setRenderGaps(boolean state)
{
- return showSequenceLogo;
+ viewStyle.setRenderGaps(state);
}
/**
- * @param showSequenceLogo
- * the new value
+ * @return
+ * @see jalview.api.ViewStyleI#getColourText()
*/
- public void setShowSequenceLogo(boolean showSequenceLogo)
+ @Override
+ public boolean getColourText()
{
- 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.getColourText();
}
/**
- * @param showConsensusHistogram
- * the showConsensusHistogram to set
+ * @param state
+ * @see jalview.api.ViewStyleI#setColourText(boolean)
*/
- public void setShowConsensusHistogram(boolean showConsensusHistogram)
+ @Override
+ public void setColourText(boolean state)
{
- this.showConsensusHistogram = showConsensusHistogram;
+ viewStyle.setColourText(state);
}
/**
- * @return the showGroupConservation
+ * @return
+ * @see jalview.api.ViewStyleI#getWrapAlignment()
*/
- public boolean isShowGroupConservation()
+ @Override
+ public boolean getWrapAlignment()
{
- return showGroupConservation;
+ return viewStyle.getWrapAlignment();
}
/**
- * @param showGroupConservation
- * the showGroupConservation to set
+ * @return
+ * @see jalview.api.ViewStyleI#getShowText()
*/
- public void setShowGroupConservation(boolean showGroupConservation)
+ @Override
+ public boolean getShowText()
{
- this.showGroupConservation = showGroupConservation;
+ return viewStyle.getShowText();
}
/**
- * @return the showGroupConsensus
+ * @return
+ * @see jalview.api.ViewStyleI#getWrappedWidth()
*/
- public boolean isShowGroupConsensus()
+ @Override
+ public int getWrappedWidth()
{
- return showGroupConsensus;
+ return viewStyle.getWrappedWidth();
}
/**
- * @param showGroupConsensus
- * the showGroupConsensus to set
+ * @param w
+ * @see jalview.api.ViewStyleI#setWrappedWidth(int)
*/
- public void setShowGroupConsensus(boolean showGroupConsensus)
+ @Override
+ public void setWrappedWidth(int w)
{
- this.showGroupConsensus = showGroupConsensus;
+ viewStyle.setWrappedWidth(w);
}
/**
- *
- * @return flag to indicate if the consensus histogram should be rendered by
- * default
+ * @return
+ * @see jalview.api.ViewStyleI#getCharHeight()
*/
@Override
- public boolean isShowConsensusHistogram()
+ public int getCharHeight()
{
- return this.showConsensusHistogram;
+ return viewStyle.getCharHeight();
}
/**
- * show non-conserved residues only
+ * @param h
+ * @see jalview.api.ViewStyleI#setCharHeight(int)
*/
- protected boolean showUnconserved = false;
+ @Override
+ public void setCharHeight(int h)
+ {
+ viewStyle.setCharHeight(h);
+ }
/**
- * when set, updateAlignment will always ensure sequences are of equal length
+ * @return
+ * @see jalview.api.ViewStyleI#getCharWidth()
*/
- private boolean padGaps = false;
+ @Override
+ public int getCharWidth()
+ {
+ return viewStyle.getCharWidth();
+ }
/**
- * when set, alignment should be reordered according to a newly opened tree
+ * @param w
+ * @see jalview.api.ViewStyleI#setCharWidth(int)
*/
- public boolean sortByTree = false;
-
- public boolean getShowUnconserved()
+ @Override
+ public void setCharWidth(int w)
{
- return showUnconserved;
+ viewStyle.setCharWidth(w);
}
- public void setShowUnconserved(boolean showunconserved)
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getShowBoxes()
+ */
+ @Override
+ public boolean getShowBoxes()
{
- showUnconserved = showunconserved;
+ return viewStyle.getShowBoxes();
}
/**
- * @param showNonconserved
- * the showUnconserved to set
+ * @return
+ * @see jalview.api.ViewStyleI#getShowUnconserved()
*/
- public void setShowunconserved(boolean displayNonconserved)
+ @Override
+ public boolean getShowUnconserved()
{
- this.showUnconserved = displayNonconserved;
+ return viewStyle.getShowUnconserved();
}
/**
- *
- *
- * @return null or the currently selected sequence region
+ * @param showunconserved
+ * @see jalview.api.ViewStyleI#setShowUnconserved(boolean)
*/
- public SequenceGroup getSelectionGroup()
+ @Override
+ public void setShowUnconserved(boolean showunconserved)
{
- return selectionGroup;
+ viewStyle.setShowUnconserved(showunconserved);
}
/**
- * Set the selection group for this window.
- *
- * @param sg
- * - group holding references to sequences in this alignment view
- *
+ * @param default1
+ * @see jalview.api.ViewStyleI#setSeqNameItalics(boolean)
*/
- public void setSelectionGroup(SequenceGroup sg)
+ @Override
+ public void setSeqNameItalics(boolean default1)
{
- selectionGroup = sg;
+ viewStyle.setSeqNameItalics(default1);
}
- 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<SequenceI, SequenceCollectionI> getHiddenRepSequences()
+ protected boolean isDataset = false;
+
+
+ public void setDataset(boolean b)
{
- return hiddenRepSequences;
+ isDataset = b;
}
- @Override
- public void setHiddenRepSequences(
- Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+ public boolean isDataset()
{
- this.hiddenRepSequences = hiddenRepSequences;
+ return isDataset;
}
- protected boolean hasHiddenColumns = false;
+ private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
+
+ protected ColumnSelection colSel = new ColumnSelection();
- public void updateHiddenColumns()
- {
- hasHiddenColumns = colSel.getHiddenColumns() != null;
- }
+ protected boolean autoCalculateConsensusAndConservation = true;
- protected boolean hasHiddenRows = false;
+ public boolean getAutoCalculateConsensusAndConservation()
+ { // BH 2019.07.24
+ return autoCalculateConsensusAndConservation;
+ }
- public boolean hasHiddenRows()
+ public void setAutoCalculateConsensusAndConservation(boolean b)
{
- return hasHiddenRows;
+ autoCalculateConsensusAndConservation = b;
}
- protected SequenceGroup selectionGroup;
+ protected boolean autoCalculateStrucConsensus = true;
- public void setSequenceSetId(String newid)
- {
- if (sequenceSetID != null)
- {
- System.err
- .println("Warning - overwriting a sequenceSetId for a viewport!");
- }
- sequenceSetID = new String(newid);
+ public boolean getAutoCalculateStrucConsensus()
+ { // BH 2019.07.24
+ return autoCalculateStrucConsensus;
}
- public String getSequenceSetId()
+ public void setAutoCalculateStrucConsensus(boolean b)
{
- if (sequenceSetID == null)
- {
- sequenceSetID = alignment.hashCode() + "";
- }
-
- return sequenceSetID;
+ autoCalculateStrucConsensus = b;
}
+ protected boolean ignoreGapsInConsensusCalculation = false;
- /**
- * unique viewId for synchronizing state (e.g. with stored Jalview Project)
- *
- */
- protected String viewId = null;
+ protected ResidueShaderI residueShading = new ResidueShader();
- 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 the 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
+
+ /*
+ * only instantiate alignment colouring once, thereafter update it;
+ * this means that any conservation or PID threshold settings
+ * persist when the alignment colour scheme is changed
+ */
+ if (residueShading == null)
{
- viewId = this.getSequenceSetId() + "." + this.hashCode() + "";
+ residueShading = new ResidueShader(viewStyle);
}
- return viewId;
- }
+ residueShading.setColourScheme(cs);
- public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap)
- {
- ignoreGapsInConsensusCalculation = b;
- if (ap != null)
+ // TODO: do threshold and increment belong in ViewStyle or ResidueShader?
+ // ...problem: groups need these, but do not currently have a ViewStyle
+
+ if (cs != null)
{
- updateConsensus(ap);
- if (globalColourScheme != null)
+ if (getConservationSelected())
{
- globalColourScheme.setThreshold(globalColourScheme.getThreshold(),
- ignoreGapsInConsensusCalculation);
+ residueShading.setConservation(hconservation);
}
+ /*
+ * reset conservation flag in case just set to false if
+ * Conservation was null (calculation still in progress)
+ */
+ residueShading.setConservationApplied(getConservationSelected());
+ residueShading.alignmentChanged(alignment, hiddenRepSequences);
}
- }
-
- 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 'apply colour to all groups' is selected... do so
+ * (but don't transfer any colour threshold settings to groups)
+ */
+ if (getColourAppliesToAllGroups())
{
- if (b)
+ for (SequenceGroup sg : getAlignment().getGroups())
{
- sgrouphash = hc;
+ /*
+ * retain any colour thresholds per group while
+ * changing choice of colour scheme (JAL-2386)
+ */
+ sg.setColourScheme(
+ cs == null ? null : cs.getInstance(this, sg));
+ if (cs != null)
+ {
+ sg.getGroupColourScheme().alignmentChanged(sg,
+ hiddenRepSequences);
+ }
}
- 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)
+ @Override
+ public ColourSchemeI getGlobalColourScheme()
{
- int hc = (colSel == null || colSel.size() == 0) ? -1 : colSel
- .hashCode();
- if (hc != -1 && hc != colselhash)
- {
- if (b)
- {
- colselhash = hc;
- }
- return true;
- }
- return false;
+ return residueShading == null ? null : residueShading.getColourScheme();
}
@Override
- public boolean getIgnoreGapsConsensus()
+ public ResidueShaderI getResidueShading()
{
- return ignoreGapsInConsensusCalculation;
+ return residueShading;
}
- // / property change stuff
+
+ protected AlignmentAnnotation consensus;
- // JBPNote Prolly only need this in the applet version.
- private final java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(
- this);
+ protected AlignmentAnnotation complementConsensus;
- protected boolean showConservation = true;
+ protected AlignmentAnnotation gapcounts;
- protected boolean showQuality = true;
+ protected AlignmentAnnotation strucConsensus;
- protected boolean showConsensus = true;
+ protected AlignmentAnnotation conservation;
+
+ protected AlignmentAnnotation quality;
+
+ protected AlignmentAnnotation[] groupConsensus;
+
+ protected AlignmentAnnotation[] groupConservation;
/**
- * Property change listener for changes in alignment
- *
- * @param listener
- * DOCUMENT ME!
+ * results of alignment consensus analysis for visible portion of view
*/
- public void addPropertyChangeListener(
- java.beans.PropertyChangeListener listener)
- {
- changeSupport.addPropertyChangeListener(listener);
- }
+ protected ProfilesI hconsensus = null;
/**
- * DOCUMENT ME!
- *
- * @param listener
- * DOCUMENT ME!
+ * results of cDNA complement consensus visible portion of view
*/
- public void removePropertyChangeListener(
- java.beans.PropertyChangeListener listener)
- {
- changeSupport.removePropertyChangeListener(listener);
- }
+ protected Hashtable<String, Object>[] hcomplementConsensus = null;
/**
- * Property change listener for changes in alignment
- *
- * @param prop
- * DOCUMENT ME!
- * @param oldvalue
- * DOCUMENT ME!
- * @param newvalue
- * DOCUMENT ME!
+ * results of secondary structure base pair consensus for visible portion of
+ * view
*/
- public void firePropertyChange(String prop, Object oldvalue,
- Object newvalue)
+ protected Hashtable<String, Object>[] hStrucConsensus = null;
+
+ protected Conservation hconservation = null;
+
+
+ @Override
+ public void setConservation(Conservation cons)
{
- changeSupport.firePropertyChange(prop, oldvalue, newvalue);
+ hconservation = cons;
}
- // common hide/show column stuff
+ /**
+ * 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!
- public void hideSelectedColumns()
+ @Override
+ public int getConsPercGaps()
{
- if (colSel.size() < 1)
- {
- return;
- }
+ return ConsPercGaps;
+ }
- colSel.hideSelectedColumns();
- setSelectionGroup(null);
+ @Override
+ public void setSequenceConsensusHash(ProfilesI hconsensus)
+ {
+ this.hconsensus = hconsensus;
+ }
- hasHiddenColumns = true;
+ @Override
+ public void setComplementConsensusHash(
+ Hashtable<String, Object>[] hconsensus)
+ {
+ this.hcomplementConsensus = hconsensus;
}
- public void hideColumns(int start, int end)
+ @Override
+ public ProfilesI getSequenceConsensusHash()
{
- if (start == end)
- {
- colSel.hideColumns(start);
- }
- else
- {
- colSel.hideColumns(start, end);
- }
+ return hconsensus;
+ }
- hasHiddenColumns = true;
+ @Override
+ public void setHmmProfiles(ProfilesI info)
+ {
+ hmmProfiles = info;
}
- public void showColumn(int col)
+ @Override
+ public ProfilesI getHmmProfiles()
{
- colSel.revealHiddenColumns(col);
- if (colSel.getHiddenColumns() == null)
- {
- hasHiddenColumns = false;
- }
+ return hmmProfiles;
}
- public void showAllHiddenColumns()
+ @Override
+ public Hashtable<String, Object>[] getComplementConsensusHash()
{
- colSel.revealAllHiddenColumns();
- hasHiddenColumns = false;
+ return hcomplementConsensus;
}
- // common hide/show seq stuff
- public void showAllHiddenSeqs()
+ @Override
+ public Hashtable<String, Object>[] getRnaStructureConsensusHash()
{
- if (alignment.getHiddenSequences().getSize() > 0)
- {
- 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++)
- {
- selectionGroup.addSequence((SequenceI) tmp.elementAt(t), false);
- }
+ return hStrucConsensus;
+ }
- hasHiddenRows = false;
- hiddenRepSequences = null;
+ @Override
+ public void setRnaStructureConsensusHash(
+ Hashtable<String, Object>[] hStrucConsensus)
+ {
+ this.hStrucConsensus = hStrucConsensus;
- firePropertyChange("alignment", null, alignment.getSequences());
- // used to set hasHiddenRows/hiddenRepSequences here, after the property
- // changed event
- sendSelection();
- }
}
- public void showSequence(int index)
+ @Override
+ public AlignmentAnnotation getAlignmentQualityAnnot()
{
- Vector tmp = alignment.getHiddenSequences().showSequence(index,
- hiddenRepSequences);
- if (tmp.size() > 0)
- {
- if (selectionGroup == null)
- {
- selectionGroup = new SequenceGroup();
- selectionGroup.setEndRes(alignment.getWidth() - 1);
- }
+ return quality;
+ }
- 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 AlignmentAnnotation getAlignmentConservationAnnotation()
+ {
+ return conservation;
}
- public void hideAllSelectedSeqs()
+ @Override
+ public AlignmentAnnotation getAlignmentConsensusAnnotation()
{
- if (selectionGroup == null || selectionGroup.getSize() < 1)
- {
- return;
- }
+ return consensus;
+ }
- SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);
+ @Override
+ public AlignmentAnnotation getAlignmentGapAnnotation()
+ {
+ return gapcounts;
+ }
- hideSequence(seqs);
+ @Override
+ public AlignmentAnnotation getComplementConsensusAnnotation()
+ {
+ return complementConsensus;
+ }
- setSelectionGroup(null);
+ @Override
+ public AlignmentAnnotation getAlignmentStrucConsensusAnnotation()
+ {
+ return strucConsensus;
}
- public void hideSequence(SequenceI[] seq)
+ protected AlignCalcManagerI2 calculator = new AlignCalcManager2();
+
+ /**
+ * trigger update of conservation annotation
+ */
+ public void updateConservation(final AlignmentViewPanel ap)
{
- if (seq != null)
+ // see note in mantis : issue number 8585
+ if (alignment.isNucleotide()
+ || (conservation == null && quality == null)
+ || !autoCalculateConsensusAndConservation)
{
- for (int i = 0; i < seq.length; i++)
- {
- alignment.getHiddenSequences().hideSequence(seq[i]);
- }
- hasHiddenRows = true;
- firePropertyChange("alignment", null, alignment.getSequences());
+ return;
+ }
+ if (calculator.getWorkersOfClass(
+ jalview.workers.ConservationThread.class).isEmpty())
+ {
+ calculator.registerWorker(
+ new jalview.workers.ConservationThread(this, ap));
}
}
- public void hideRepSequences(SequenceI repSequence, SequenceGroup sg)
+ /**
+ * trigger update of consensus annotation
+ */
+ public void updateConsensus(final AlignmentViewPanel ap)
{
- int sSize = sg.getSize();
- if (sSize < 2)
+ // see note in mantis : issue number 8585
+ if (consensus == null || !autoCalculateConsensusAndConservation)
{
return;
}
-
- if (hiddenRepSequences == null)
+ if (calculator.getWorkersOfClass(ConsensusThread.class).isEmpty())
{
- hiddenRepSequences = new Hashtable();
+ calculator.registerWorker(new ConsensusThread(this, ap));
}
- 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++)
+ /*
+ * A separate thread to compute cDNA consensus for a protein alignment
+ * which has mapping to cDNA
+ */
+ final AlignmentI al = this.getAlignment();
+ if (!al.isNucleotide() && al.getCodonFrames() != null
+ && !al.getCodonFrames().isEmpty())
{
- if (sg.getSequenceAt(i) != repSequence)
+ /*
+ * fudge - check first for protein-to-nucleotide mappings
+ * (we don't want to do this for protein-to-protein)
+ */
+ boolean doConsensus = false;
+ for (AlignedCodonFrame mapping : al.getCodonFrames())
{
- if (index == sSize - 1)
+ // TODO hold mapping type e.g. dna-to-protein in AlignedCodonFrame?
+ MapList[] mapLists = mapping.getdnaToProt();
+ // mapLists can be empty if project load has not finished resolving seqs
+ if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
{
- return;
+ doConsensus = true;
+ break;
+ }
+ }
+ if (doConsensus)
+ {
+ if (calculator.getWorkersOfClass(ComplementConsensusThread.class).isEmpty())
+ {
+ calculator.registerWorker(new ComplementConsensusThread(this, ap));
}
-
- 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 hiddenRepSequences != null
- && hiddenRepSequences.containsKey(seq);
- }
-
- public SequenceGroup getRepresentedSequences(SequenceI seq)
- {
- return (SequenceGroup) (hiddenRepSequences == null ? null
- : hiddenRepSequences.get(seq));
}
- public int adjustForHiddenSeqs(int alignmentIndex)
+ @Override
+ public void initInformationWorker(final AlignmentViewPanel ap)
{
- return alignment.getHiddenSequences().adjustForHiddenSeqs(
- alignmentIndex);
+ if (calculator.getWorkersOfClass(InformationThread.class).isEmpty())
+ {
+ calculator.registerWorker(new InformationThread(this, ap));
+ }
}
-
- // Selection manipulation
- /**
- * broadcast selection to any interested parties
- */
- public abstract void sendSelection();
-
- public void invertColumnSelection()
+ // --------START Structure Conservation
+ public void updateStrucConsensus(final AlignmentViewPanel ap)
{
- colSel.invertColumnSelection(0, alignment.getWidth());
- }
+ if (autoCalculateStrucConsensus && strucConsensus == null
+ && alignment.isNucleotide() && alignment.hasRNAStructure())
+ {
+ // secondary structure has been added - so init the consensus line
+ initRNAStructure();
+ }
- /**
- * 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
- */
- 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)
+ // see note in mantis : issue number 8585
+ if (strucConsensus == null || !autoCalculateStrucConsensus)
{
- 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
- }
+ return;
}
- else
+ if (calculator.getWorkersOfClass(StrucConsensusThread.class).isEmpty())
{
- sequences = selectionGroup.getSelectionAsNewSequences(alignment);
+ calculator.registerWorker(new StrucConsensusThread(this, ap));
}
+ }
- return sequences;
+ public boolean isCalcInProgress()
+ {
+ return calculator.isWorking();
}
- /**
- * get the currently selected sequence objects or all the sequences in the
- * alignment.
- *
- * @return array of references to sequence objects
- */
- public SequenceI[] getSequenceSelection()
+ @Override
+ public boolean isCalculationInProgress(
+ AlignmentAnnotation alignmentAnnotation)
{
- SequenceI[] sequences = null;
- if (selectionGroup != null)
+ if (!alignmentAnnotation.autoCalculated)
{
- sequences = selectionGroup.getSequencesInOrder(alignment);
+ return false;
}
- if (sequences == null)
+ if (calculator.isWorkingWithAnnotation(alignmentAnnotation))
{
- sequences = alignment.getSequencesArray();
+ // System.err.println("grey out ("+alignmentAnnotation.label+")");
+ return true;
}
- return sequences;
+ return false;
}
+ private ScheduledExecutorService serviceExecutor = Executors.newSingleThreadScheduledExecutor();
+
/**
- * 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.
+ * Get a default scheduled executor service which can be used by
+ * services and calculators to run parallel jobs associated with this
+ * viewport.
*
- * @return String[]
+ * @return default service executor of that viewport
*/
- public jalview.datamodel.CigarArray getViewAsCigars(
- boolean selectedRegionOnly)
+ public ScheduledExecutorService getServiceExecutor()
{
- return new jalview.datamodel.CigarArray(alignment,
- (hasHiddenColumns ? colSel : null),
- (selectedRegionOnly ? selectionGroup : null));
+ return serviceExecutor;
}
- /**
- * 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
- */
- public jalview.datamodel.AlignmentView getAlignmentView(
- boolean selectedOnly)
+ public void setAlignment(AlignmentI align)
{
- return getAlignmentView(selectedOnly, false);
+ this.alignment = align;
}
/**
- * 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
+ * Clean up references when this viewport is closed
*/
- public jalview.datamodel.AlignmentView getAlignmentView(
- boolean selectedOnly, boolean markGroups)
+ @Override
+ public void dispose()
{
- return new AlignmentView(alignment, colSel, selectionGroup,
- hasHiddenColumns, selectedOnly, markGroups);
+ /*
+ * defensively null out references to large objects in case
+ * this object is not garbage collected (as if!)
+ */
+ consensus = null;
+ complementConsensus = null;
+ strucConsensus = null;
+ conservation = null;
+ quality = null;
+ consensusProfiles = null;
+ groupConsensus = null;
+ groupConservation = null;
+ hconsensus = null;
+ hconservation = null;
+ hcomplementConsensus = null;
+ gapcounts = null;
+ calculator.shutdown();
+ calculator = null;
+ serviceExecutor.shutdown();
+ serviceExecutor = null;
+ residueShading = null; // may hold a reference to Consensus
+ changeSupport = null;
+ ranges = null;
+ currentTree = null;
+ selectionGroup = null;
+ colSel = null;
+ setAlignment(null);
+ }
+
+ @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 AlignCalcManagerI2 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;
+
+ /**
+ * should hmm profile be rendered by default
+ */
+ protected boolean hmmShowSequenceLogo = false;
+
+ /**
+ * should hmm profile be rendered normalised to row height
+ */
+ protected boolean hmmNormaliseSequenceLogo = false;
+
+ /**
+ * should information histograms be rendered by default
+ */
+ protected boolean hmmShowHistogram = true;
+
+ /**
+ * @return the showConsensusProfile
+ */
+ @Override
+ public boolean isShowSequenceLogo()
+ {
+ return showSequenceLogo;
+ }
+
+ /**
+ * @return the showInformationProfile
+ */
+ @Override
+ public boolean isShowHMMSequenceLogo()
+ {
+ return hmmShowSequenceLogo;
+ }
+
+ /**
+ * @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;
+ for (AlignCalcWorkerI worker : calculator.getWorkers())
+ {
+ if (worker.getClass().equals(ConsensusThread.class) ||
+ worker.getClass().equals(ComplementConsensusThread.class) ||
+ worker.getClass().equals(StrucConsensusThread.class))
+ {
+ worker.updateAnnotation();
+ }
+ }
+ }
+ this.showSequenceLogo = showSequenceLogo;
+ }
+
+ public void setShowHMMSequenceLogo(boolean showHMMSequenceLogo)
+ {
+ if (showHMMSequenceLogo != this.hmmShowSequenceLogo)
+ {
+ this.hmmShowSequenceLogo = showHMMSequenceLogo;
+ // TODO: updateAnnotation if description (tooltip) will show
+ // profile in place of information content?
+ // calculator.updateAnnotationFor(InformationThread.class);
+ }
+ this.hmmShowSequenceLogo = showHMMSequenceLogo;
+ }
+ /**
+ * @param showConsensusHistogram
+ * the showConsensusHistogram to set
+ */
+ public void setShowConsensusHistogram(boolean showConsensusHistogram)
+ {
+ this.showConsensusHistogram = showConsensusHistogram;
+ }
+
+ /**
+ * @param showInformationHistogram
+ */
+ public void setShowInformationHistogram(boolean showInformationHistogram)
+ {
+ this.hmmShowHistogram = showInformationHistogram;
+ }
+
+ /**
+ * @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;
+ }
+
+ /**
+ *
+ * @return flag to indicate if the information content histogram should be
+ * rendered by default
+ */
+ @Override
+ public boolean isShowInformationHistogram()
+ {
+ return this.hmmShowHistogram;
+ }
+
+ /**
+ * 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. Also sets the current alignment as
+ * the context for the group, if it does not already have one.
+ *
+ * @param sg
+ * - group holding references to sequences in this alignment view
+ *
+ */
+ @Override
+ public void setSelectionGroup(SequenceGroup sg)
+ {
+ selectionGroup = sg;
+ if (sg != null && sg.getContext() == null)
+ {
+ sg.setContext(alignment);
+ }
+ }
+
+ public void setHiddenColumns(HiddenColumns hidden)
+ {
+ this.alignment.setHiddenColumns(hidden);
+ }
+
+ @Override
+ public ColumnSelection getColumnSelection()
+ {
+ return colSel;
+ }
+
+ @Override
+ public void setColumnSelection(ColumnSelection colSel)
+ {
+ this.colSel = colSel;
+ if (colSel != null)
+ {
+ updateHiddenColumns();
+ }
+ isColSelChanged(true);
+ }
+
+ /**
+ *
+ * @return
+ */
+ @Override
+ public Map<SequenceI, SequenceCollectionI> getHiddenRepSequences()
+ {
+ return hiddenRepSequences;
+ }
+
+ @Override
+ public void setHiddenRepSequences(
+ Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+ {
+ this.hiddenRepSequences = hiddenRepSequences;
+ }
+
+ @Override
+ public boolean hasSelectedColumns()
+ {
+ ColumnSelection columnSelection = getColumnSelection();
+ return columnSelection != null && columnSelection.hasSelectedColumns();
+ }
+
+ @Override
+ public boolean hasHiddenColumns()
+ {
+ return alignment.getHiddenColumns() != null
+ && alignment.getHiddenColumns().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;
+ }
+
+ public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap)
+ {
+ ignoreGapsInConsensusCalculation = b;
+ if (ap != null)
+ {
+ updateConsensus(ap);
+ if (residueShading != null)
+ {
+ residueShading.setThreshold(residueShading.getThreshold(),
+ ignoreGapsInConsensusCalculation);
+ }
+ }
+ }
+
+ public void setIgnoreBelowBackground(boolean b, AlignmentViewPanel ap)
+ {
+ ignoreBelowBackGroundFrequencyCalculation = b;
+ }
+
+ public void setInfoLetterHeight(boolean b, AlignmentViewPanel ap)
+ {
+ infoLetterHeight = b;
+ }
+
+ 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 updateHash
+ * update the record of last hash value
+ * @return true if colsel changed since last call (when b is true)
+ */
+ public boolean isColSelChanged(boolean updateHash)
+ {
+ int hc = (colSel == null || colSel.isEmpty()) ? -1 : colSel.hashCode();
+ if (hc != -1 && hc != colselhash)
+ {
+ if (updateHash)
+ {
+ colselhash = hc;
+ }
+ return true;
+ }
+ notifySequence();
+ return false;
+ }
+
+ @Override
+ public boolean isIgnoreGapsConsensus()
+ {
+ return ignoreGapsInConsensusCalculation;
+ }
+
+ @Override
+ public boolean isIgnoreBelowBackground()
+ {
+ return ignoreBelowBackGroundFrequencyCalculation;
+ }
+
+ @Override
+ public boolean isInfoLetterHeight()
+ {
+ return infoLetterHeight;
+ }
+ // property change stuff
+ // JBPNote Prolly only need this in the applet version.
+ private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+ this);
+
+ protected boolean showConservation = true;
+
+ protected boolean showQuality = true;
+
+ protected boolean showConsensus = true;
+
+ protected boolean showOccupancy = true;
+
+ private Map<SequenceI, Color> sequenceColours = new HashMap<>();
+
+ protected SequenceAnnotationOrder sortAnnotationsBy = null;
+
+ protected boolean showAutocalculatedAbove;
+
+ /**
+ * when set, view will scroll to show the highlighted position
+ */
+ private boolean followHighlight = true;
+
+ /**
+ * 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)
+ {
+ if (changeSupport != null)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
+ }
+
+
+ // common hide/show column stuff
+
+ public void hideSelectedColumns()
+ {
+ if (colSel.isEmpty())
+ {
+ return;
+ }
+
+ colSel.hideSelectedColumns(alignment);
+ setSelectionGroup(null);
+ isColSelChanged(true);
+ }
+
+ public void hideColumns(int start, int end)
+ {
+ if (start == end)
+ {
+ colSel.hideSelectedColumns(start, alignment.getHiddenColumns());
+ }
+ else
+ {
+ alignment.getHiddenColumns().hideColumns(start, end);
+ }
+ isColSelChanged(true);
+ }
+
+ public void showColumn(int col)
+ {
+ alignment.getHiddenColumns().revealHiddenColumns(col, colSel);
+ isColSelChanged(true);
+ }
+
+ public void showAllHiddenColumns()
+ {
+ alignment.getHiddenColumns().revealAllHiddenColumns(colSel);
+ isColSelChanged(true);
+ }
+
+ // common hide/show seq stuff
+ public void showAllHiddenSeqs()
+ {
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+
+ if (alignment.getHiddenSequences().getSize() > 0)
+ {
+ if (selectionGroup == null)
+ {
+ selectionGroup = new SequenceGroup();
+ selectionGroup.setEndRes(alignment.getWidth() - 1);
+ }
+ List<SequenceI> tmp = alignment.getHiddenSequences()
+ .showAll(hiddenRepSequences);
+ for (SequenceI seq : tmp)
+ {
+ selectionGroup.addSequence(seq, false);
+ setSequenceAnnotationsVisible(seq, true);
+ }
+
+ hiddenRepSequences = null;
+
+ ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
+ // used to set hasHiddenRows/hiddenRepSequences here, after the property
+ // changed event
+ notifySequence();
+ sendSelection();
+ }
+ }
+
+ public void showSequence(int index)
+ {
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+
+ List<SequenceI> 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);
+ }
+
+ ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
+ notifyAlignment();
+ 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)
+ {
+ /*
+ * cache offset to first visible sequence
+ */
+ int startSeq = ranges.getStartSeq();
+
+ if (seq != null)
+ {
+ for (int i = 0; i < seq.length; i++)
+ {
+ alignment.getHiddenSequences().hideSequence(seq[i]);
+ setSequenceAnnotationsVisible(seq[i], false);
+ }
+ ranges.setStartSeq(startSeq);
+ notifyAlignment();
+ }
+ }
+
+ /**
+ * Hides the specified sequence, or the sequences it represents
+ *
+ * @param sequence
+ * the sequence to hide, or keep as representative
+ * @param representGroup
+ * if true, hide the current selection group except for the
+ * representative sequence
+ */
+ public void hideSequences(SequenceI sequence, boolean representGroup)
+ {
+ if (selectionGroup == null || selectionGroup.getSize() < 1)
+ {
+ hideSequence(new SequenceI[] { sequence });
+ return;
+ }
+
+ if (representGroup)
+ {
+ hideRepSequences(sequence, selectionGroup);
+ setSelectionGroup(null);
+ return;
+ }
+
+ int gsize = selectionGroup.getSize();
+ SequenceI[] hseqs = selectionGroup.getSequences()
+ .toArray(new SequenceI[gsize]);
+
+ hideSequence(hseqs);
+ setSelectionGroup(null);
+ sendSelection();
+ }
+
+ /**
+ * Set visibility for any annotations for the given sequence.
+ *
+ * @param sequenceI
+ */
+ protected void setSequenceAnnotationsVisible(SequenceI sequenceI,
+ boolean visible)
+ {
+ AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
+ if (anns != null)
+ {
+ for (AlignmentAnnotation ann : anns)
+ {
+ 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);
+
+ }
+
+ /**
+ *
+ * @return null or the current reference sequence
+ */
+ public SequenceI getReferenceSeq()
+ {
+ return alignment.getSeqrep();
+ }
+
+ /**
+ * @param seq
+ * @return true iff seq is the reference for the alignment
+ */
+ public boolean isReferenceSeq(SequenceI seq)
+ {
+ return alignment.getSeqrep() == seq;
+ }
+
+ /**
+ *
+ * @param seq
+ * @return true if there are sequences represented by this sequence that are
+ * currently hidden
+ */
+ public boolean isHiddenRepSequence(SequenceI seq)
+ {
+ return (hiddenRepSequences != null
+ && hiddenRepSequences.containsKey(seq));
+ }
+
+ /**
+ *
+ * @param seq
+ * @return null or a sequence group containing the sequences that seq
+ * represents
+ */
+ 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(), alignment);
+ isColSelChanged(true);
+ }
+
+ @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 jalview.datamodel.AlignmentView getAlignmentView(
+ boolean selectedOnly)
+ {
+ return getAlignmentView(selectedOnly, false);
+ }
+
+ @Override
+ public jalview.datamodel.AlignmentView getAlignmentView(
+ boolean selectedOnly, boolean markGroups)
+ {
+ return new AlignmentView(alignment, alignment.getHiddenColumns(),
+ selectionGroup,
+ alignment.getHiddenColumns() != null
+ && alignment.getHiddenColumns().hasHiddenColumns(),
+ selectedOnly, markGroups);
+ }
+
+ @Override
+ public String[] getViewAsString(boolean selectedRegionOnly)
+ {
+ return getViewAsString(selectedRegionOnly, true);
+ }
+
+ @Override
+ public String[] getViewAsString(boolean selectedRegionOnly,
+ boolean exportHiddenSeqs)
+ {
+ 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
+ {
+ if (hasHiddenRows() && exportHiddenSeqs)
+ {
+ AlignmentI fullAlignment = alignment.getHiddenSequences()
+ .getFullAlignment();
+ iSize = fullAlignment.getHeight();
+ seqs = fullAlignment.getSequencesArray();
+ end = fullAlignment.getWidth();
+ }
+ else
+ {
+ iSize = alignment.getHeight();
+ seqs = alignment.getSequencesArray();
+ end = alignment.getWidth();
+ }
+ }
+
+ selection = new String[iSize];
+ if (alignment.getHiddenColumns() != null
+ && alignment.getHiddenColumns().hasHiddenColumns())
+ {
+ for (i = 0; i < iSize; i++)
+ {
+ Iterator<int[]> blocks = alignment.getHiddenColumns()
+ .getVisContigsIterator(start, end + 1, false);
+ selection[i] = seqs[i].getSequenceStringFromIterator(blocks);
+ }
+ }
+ else
+ {
+ for (i = 0; i < iSize; i++)
+ {
+ selection[i] = seqs[i].getSequenceAsString(start, end);
+ }
+
+ }
+ return selection;
+ }
+
+ @Override
+ public List<int[]> getVisibleRegionBoundaries(int min, int max)
+ {
+ ArrayList<int[]> regions = new ArrayList<>();
+ int start = min;
+ int end = max;
+
+ do
+ {
+ HiddenColumns hidden = alignment.getHiddenColumns();
+ if (hidden != null && hidden.hasHiddenColumns())
+ {
+ if (start == 0)
+ {
+ start = hidden.visibleToAbsoluteColumn(start);
+ }
+
+ end = hidden.getNextHiddenBoundary(false, start);
+ if (start == end)
+ {
+ end = max;
+ }
+ if (end > max)
+ {
+ end = max;
+ }
+ }
+
+ regions.add(new int[] { start, end });
+
+ if (hidden != null && hidden.hasHiddenColumns())
+ {
+ start = hidden.visibleToAbsoluteColumn(end);
+ start = hidden.getNextHiddenBoundary(true, start) + 1;
+ }
+ } while (end < max);
+
+ // int[][] startEnd = new int[regions.size()][2];
+
+ return regions;
+ }
+
+ @Override
+ public List<AlignmentAnnotation> getVisibleAlignmentAnnotation(
+ boolean selectedOnly)
+ {
+ ArrayList<AlignmentAnnotation> ala = new ArrayList<>();
+ AlignmentAnnotation[] aa;
+ if ((aa = alignment.getAlignmentAnnotation()) != null)
+ {
+ for (AlignmentAnnotation annot : aa)
+ {
+ AlignmentAnnotation clone = new AlignmentAnnotation(annot);
+ if (selectedOnly && selectionGroup != null)
+ {
+ clone.makeVisibleAnnotation(
+ selectionGroup.getStartRes(), selectionGroup.getEndRes(),
+ alignment.getHiddenColumns());
+ }
+ else
+ {
+ clone.makeVisibleAnnotation(alignment.getHiddenColumns());
+ }
+ 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 (autoCalculateConsensusAndConservation)
+ {
+ updateConsensus(ap);
+ }
+ if (hconsensus != null && autoCalculateConsensusAndConservation)
+ {
+ updateConservation(ap);
+ }
+ if (autoCalculateStrucConsensus)
+ {
+ updateStrucConsensus(ap);
+ }
+
+ // Reset endRes of groups if beyond alignment width
+ int alWidth = alignment.getWidth();
+ List<SequenceGroup> 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);
+ }
+
+ updateAllColourSchemes();
+ calculator.restartWorkers();
+ }
+
+ /**
+ * reset scope and do calculations for all applied colourschemes on alignment
+ */
+ void updateAllColourSchemes()
+ {
+ ResidueShaderI rs = residueShading;
+ if (rs != null)
+ {
+ rs.alignmentChanged(alignment, hiddenRepSequences);
+
+ rs.setConsensus(hconsensus);
+ if (rs.conservationApplied())
+ {
+ rs.setConservation(Conservation.calculateConservation("All",
+ alignment.getSequences(), 0, alignment.getWidth(), false,
+ getConsPercGaps(), false));
+ }
+ }
+
+ for (SequenceGroup sg : alignment.getGroups())
+ {
+ if (sg.cs != null)
+ {
+ sg.cs.alignmentChanged(sg, hiddenRepSequences);
+ }
+ sg.recalcConservation();
+ }
+ }
+
+ 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",
+ MessageManager.getString("label.consensus_descr"),
+ new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+ initConsensus(consensus);
+ initGapCounts();
+
+ initComplementConsensus();
+ }
+ }
+
+ /**
+ * If this is a protein alignment and there are mappings to cDNA, adds the
+ * cDNA consensus annotation and returns true, else returns false.
+ */
+ public boolean initComplementConsensus()
+ {
+ if (!alignment.isNucleotide())
+ {
+ final List<AlignedCodonFrame> codonMappings = alignment
+ .getCodonFrames();
+ if (codonMappings != null && !codonMappings.isEmpty())
+ {
+ boolean doConsensus = false;
+ for (AlignedCodonFrame mapping : codonMappings)
+ {
+ // TODO hold mapping type e.g. dna-to-protein in AlignedCodonFrame?
+ MapList[] mapLists = mapping.getdnaToProt();
+ // mapLists can be empty if project load has not finished resolving
+ // seqs
+ if (mapLists.length > 0 && mapLists[0].getFromRatio() == 3)
+ {
+ doConsensus = true;
+ break;
+ }
+ }
+ if (doConsensus)
+ {
+ complementConsensus = new AlignmentAnnotation("cDNA Consensus",
+ MessageManager
+ .getString("label.complement_consensus_descr"),
+ new Annotation[1], 0f, 100f,
+ AlignmentAnnotation.BAR_GRAPH);
+ initConsensus(complementConsensus);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void initConsensus(AlignmentAnnotation aa)
+ {
+ aa.hasText = true;
+ aa.autoCalculated = true;
+
+ if (showConsensus)
+ {
+ alignment.addAnnotation(aa);
+ }
+ }
+
+ // these should be extracted from the view model - style and settings for
+ // derived annotation
+ private void initGapCounts()
+ {
+ if (showOccupancy)
+ {
+ gapcounts = new AlignmentAnnotation("Occupancy",
+ MessageManager.getString("label.occupancy_descr"),
+ new Annotation[1], 0f, alignment.getHeight(),
+ AlignmentAnnotation.BAR_GRAPH);
+ gapcounts.hasText = true;
+ gapcounts.autoCalculated = true;
+ gapcounts.scaleColLabel = true;
+ gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
+
+ alignment.addAnnotation(gapcounts);
+ }
+ }
+
+ private void initConservation()
+ {
+ if (showConservation)
+ {
+ if (conservation == null)
+ {
+ conservation = new AlignmentAnnotation("Conservation",
+ MessageManager.formatMessage("label.conservation_descr",
+ getConsPercGaps()),
+ 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",
+ MessageManager.getString("label.quality_descr"),
+ 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",
+ MessageManager.getString("label.strucconsensus_descr"),
+ new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
+ strucConsensus.hasText = true;
+ strucConsensus.autoCalculated = true;
+
+ if (showConsensus)
+ {
+ alignment.addAnnotation(strucConsensus);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.api.AlignViewportI#calcPanelHeight()
+ */
+ @Override
+ public int calcPanelHeight()
+ {
+ // 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();
+ boolean showHMMPrf = isShowHMMSequenceLogo();
+ boolean showInfoHist = isShowInformationHistogram();
+ boolean normHMMLogo = isNormaliseHMMSequenceLogo();
+
+ /**
+ * 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<SequenceGroup> 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);
+ sg.setShowHMMSequenceLogo(showHMMPrf);
+ sg.setShowInformationHistogram(showInfoHist);
+ sg.setNormaliseHMMSequenceLogo(normHMMLogo);
+ }
+ 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();
+ }
+
+ @Override
+ public boolean isDisplayReferenceSeq()
+ {
+ return alignment.hasSeqrep() && viewStyle.isDisplayReferenceSeq();
+ }
+
+ @Override
+ public void setDisplayReferenceSeq(boolean displayReferenceSeq)
+ {
+ viewStyle.setDisplayReferenceSeq(displayReferenceSeq);
+ }
+
+ @Override
+ public boolean isColourByReferenceSeq()
+ {
+ return alignment.hasSeqrep() && viewStyle.isColourByReferenceSeq();
+ }
+
+ @Override
+ public Color getSequenceColour(SequenceI seq)
+ {
+ Color sqc = sequenceColours.get(seq);
+ return (sqc == null ? Color.white : sqc);
+ }
+
+ @Override
+ public void setSequenceColour(SequenceI seq, Color col)
+ {
+ if (col == null)
+ {
+ sequenceColours.remove(seq);
+ }
+ else
+ {
+ sequenceColours.put(seq, col);
+ }
+ }
+
+ @Override
+ public void updateSequenceIdColours()
+ {
+ for (SequenceGroup sg : alignment.getGroups())
+ {
+ if (sg.idColour != null)
+ {
+ for (SequenceI s : sg.getSequences(getHiddenRepSequences()))
+ {
+ sequenceColours.put(s, sg.idColour);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void clearSequenceColours()
+ {
+ sequenceColours.clear();
+ }
+
+ @Override
+ public AlignViewportI getCodingComplement()
+ {
+ return this.codingComplement;
+ }
+
+ /**
+ * 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 (this == av)
+ {
+ System.err.println("Ignoring recursive setCodingComplement request");
+ }
+ else
+ {
+ this.codingComplement = av;
+ // avoid infinite recursion!
+ if (av.getCodingComplement() != this)
+ {
+ av.setCodingComplement(this);
+ }
+ }
+ }
+
+ @Override
+ public boolean isNucleotide()
+ {
+ return getAlignment() == null ? false : getAlignment().isNucleotide();
+ }
+
+ @Override
+ public FeaturesDisplayedI getFeaturesDisplayed()
+ {
+ return featuresDisplayed;
+ }
+
+ @Override
+ public void setFeaturesDisplayed(FeaturesDisplayedI featuresDisplayedI)
+ {
+ featuresDisplayed = featuresDisplayedI;
+ }
+
+ @Override
+ public boolean areFeaturesDisplayed()
+ {
+ return featuresDisplayed != null
+ && featuresDisplayed.getRegisteredFeaturesCount() > 0;
+ }
+
+ /**
+ * set the flag
+ *
+ * @param b
+ * features are displayed if true
+ */
+ @Override
+ public void setShowSequenceFeatures(boolean b)
+ {
+ viewStyle.setShowSequenceFeatures(b);
+ }
+
+ @Override
+ public boolean isShowSequenceFeatures()
+ {
+ return viewStyle.isShowSequenceFeatures();
+ }
+
+ @Override
+ public void setShowSequenceFeaturesHeight(boolean selected)
+ {
+ viewStyle.setShowSequenceFeaturesHeight(selected);
+ }
+
+ @Override
+ public boolean isShowSequenceFeaturesHeight()
+ {
+ return viewStyle.isShowSequenceFeaturesHeight();
+ }
+
+ @Override
+ public void setShowAnnotation(boolean b)
+ {
+ viewStyle.setShowAnnotation(b);
+ }
+
+ @Override
+ public boolean isShowAnnotation()
+ {
+ return viewStyle.isShowAnnotation();
+ }
+
+ @Override
+ public boolean isRightAlignIds()
+ {
+ return viewStyle.isRightAlignIds();
+ }
+
+ @Override
+ public void setRightAlignIds(boolean rightAlignIds)
+ {
+ viewStyle.setRightAlignIds(rightAlignIds);
+ }
+
+ @Override
+ public boolean getConservationSelected()
+ {
+ return viewStyle.getConservationSelected();
+ }
+
+ @Override
+ public void setShowBoxes(boolean state)
+ {
+ viewStyle.setShowBoxes(state);
+ }
+
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getTextColour()
+ */
+ @Override
+ public Color getTextColour()
+ {
+ return viewStyle.getTextColour();
+ }
+
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getTextColour2()
+ */
+ @Override
+ public Color getTextColour2()
+ {
+ return viewStyle.getTextColour2();
+ }
+
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getThresholdTextColour()
+ */
+ @Override
+ public int getThresholdTextColour()
+ {
+ return viewStyle.getThresholdTextColour();
+ }
+
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#isConservationColourSelected()
+ */
+ @Override
+ public boolean isConservationColourSelected()
+ {
+ return viewStyle.isConservationColourSelected();
}
/**
- * 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#isRenderGaps()
*/
- public String[] getViewAsString(boolean selectedRegionOnly)
+ @Override
+ public boolean isRenderGaps()
{
- 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();
- }
+ return viewStyle.isRenderGaps();
+ }
- 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
+ * @see jalview.api.ViewStyleI#isShowColourText()
+ */
+ @Override
+ public boolean isShowColourText()
+ {
+ return viewStyle.isShowColourText();
+ }
- }
- return selection;
+ /**
+ * @param conservationColourSelected
+ * @see jalview.api.ViewStyleI#setConservationColourSelected(boolean)
+ */
+ @Override
+ public void setConservationColourSelected(
+ boolean conservationColourSelected)
+ {
+ viewStyle.setConservationColourSelected(conservationColourSelected);
}
/**
- * 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 showColourText
+ * @see jalview.api.ViewStyleI#setShowColourText(boolean)
*/
- public int[][] getVisibleRegionBoundaries(int min, int max)
+ @Override
+ public void setShowColourText(boolean showColourText)
{
- Vector regions = new Vector();
- int start = min;
- int end = max;
+ viewStyle.setShowColourText(showColourText);
+ }
- do
+ /**
+ * @param textColour
+ * @see jalview.api.ViewStyleI#setTextColour(java.awt.Color)
+ */
+ @Override
+ public void setTextColour(Color textColour)
+ {
+ viewStyle.setTextColour(textColour);
+ }
+
+ /**
+ * @param thresholdTextColour
+ * @see jalview.api.ViewStyleI#setThresholdTextColour(int)
+ */
+ @Override
+ public void setThresholdTextColour(int thresholdTextColour)
+ {
+ viewStyle.setThresholdTextColour(thresholdTextColour);
+ }
+
+ /**
+ * @param textColour2
+ * @see jalview.api.ViewStyleI#setTextColour2(java.awt.Color)
+ */
+ @Override
+ public void setTextColour2(Color textColour2)
+ {
+ viewStyle.setTextColour2(textColour2);
+ }
+
+ @Override
+ public ViewStyleI getViewStyle()
+ {
+ return new ViewStyle(viewStyle);
+ }
+
+ @Override
+ public void setViewStyle(ViewStyleI settingsForView)
+ {
+ viewStyle = new ViewStyle(settingsForView);
+ if (residueShading != null)
{
- if (hasHiddenColumns)
- {
- if (start == 0)
- {
- start = colSel.adjustForHiddenColumns(start);
- }
+ residueShading.setConservationApplied(
+ settingsForView.isConservationColourSelected());
+ }
+ }
- end = colSel.getHiddenBoundaryRight(start);
- if (start == end)
- {
- end = max;
- }
- if (end > max)
- {
- end = max;
- }
- }
+ @Override
+ public boolean sameStyle(ViewStyleI them)
+ {
+ return viewStyle.sameStyle(them);
+ }
- regions.addElement(new int[]
- { start, end });
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#getIdWidth()
+ */
+ @Override
+ public int getIdWidth()
+ {
+ return viewStyle.getIdWidth();
+ }
- if (hasHiddenColumns)
- {
- start = colSel.adjustForHiddenColumns(end);
- start = colSel.getHiddenBoundaryLeft(start) + 1;
- }
- } while (end < max);
+ /**
+ * @param i
+ * @see jalview.api.ViewStyleI#setIdWidth(int)
+ */
+ @Override
+ public void setIdWidth(int i)
+ {
+ viewStyle.setIdWidth(i);
+ }
- int[][] startEnd = new int[regions.size()][2];
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#isCentreColumnLabels()
+ */
+ @Override
+ public boolean isCentreColumnLabels()
+ {
+ return viewStyle.isCentreColumnLabels();
+ }
- regions.copyInto(startEnd);
+ /**
+ * @param centreColumnLabels
+ * @see jalview.api.ViewStyleI#setCentreColumnLabels(boolean)
+ */
+ @Override
+ public void setCentreColumnLabels(boolean centreColumnLabels)
+ {
+ viewStyle.setCentreColumnLabels(centreColumnLabels);
+ }
- return startEnd;
+ /**
+ * @param showdbrefs
+ * @see jalview.api.ViewStyleI#setShowDBRefs(boolean)
+ */
+ @Override
+ public void setShowDBRefs(boolean showdbrefs)
+ {
+ viewStyle.setShowDBRefs(showdbrefs);
+ }
+ /**
+ * @return
+ * @see jalview.api.ViewStyleI#isShowDBRefs()
+ */
+ @Override
+ public boolean isShowDBRefs()
+ {
+ return viewStyle.isShowDBRefs();
}
/**
- * @return the padGaps
+ * @return
+ * @see jalview.api.ViewStyleI#isShowNPFeats()
*/
- public boolean isPadGaps()
+ @Override
+ public boolean isShowNPFeats()
{
- return padGaps;
+ return viewStyle.isShowNPFeats();
}
/**
- * @param padGaps
- * the padGaps to set
+ * @param shownpfeats
+ * @see jalview.api.ViewStyleI#setShowNPFeats(boolean)
*/
- public void setPadGaps(boolean padGaps)
+ @Override
+ public void setShowNPFeats(boolean shownpfeats)
{
- this.padGaps = padGaps;
+ viewStyle.setShowNPFeats(shownpfeats);
}
+ public abstract StructureSelectionManager getStructureSelectionManager();
+
/**
- * apply any post-edit constraints and trigger any calculations needed after
- * an edit has been performed on the alignment
+ * Add one command to the command history list.
*
- * @param ap
+ * @param command
*/
- public void alignmentChanged(AlignmentViewPanel ap)
+ public void addToHistoryList(CommandI command)
{
- if (isPadGaps())
+ if (this.historyList != null)
{
- alignment.padGaps();
+ this.historyList.push(command);
+ broadcastCommand(command, false);
}
- if (autoCalculateConsensus)
+ }
+
+ protected void broadcastCommand(CommandI command, boolean undo)
+ {
+ getStructureSelectionManager().commandPerformed(command, undo,
+ getVamsasSource());
+ }
+
+ /**
+ * Add one command to the command redo list.
+ *
+ * @param command
+ */
+ public void addToRedoList(CommandI command)
+ {
+ if (this.redoList != null)
{
- updateConsensus(ap);
+ this.redoList.push(command);
}
- if (hconsensus != null && autoCalculateConsensus)
+ broadcastCommand(command, true);
+ }
+
+ /**
+ * Clear the command redo list.
+ */
+ public void clearRedoList()
+ {
+ if (this.redoList != null)
{
- updateConservation(ap);
+ this.redoList.clear();
}
- if (autoCalculateStrucConsensus)
+ }
+
+ public void setHistoryList(Deque<CommandI> list)
+ {
+ this.historyList = list;
+ }
+
+ public Deque<CommandI> getHistoryList()
+ {
+ return this.historyList;
+ }
+
+ public void setRedoList(Deque<CommandI> list)
+ {
+ this.redoList = list;
+ }
+
+ public Deque<CommandI> getRedoList()
+ {
+ return this.redoList;
+ }
+
+ @Override
+ public VamsasSource getVamsasSource()
+ {
+ return this;
+ }
+
+ public SequenceAnnotationOrder getSortAnnotationsBy()
+ {
+ return sortAnnotationsBy;
+ }
+
+ public void setSortAnnotationsBy(
+ SequenceAnnotationOrder sortAnnotationsBy)
+ {
+ this.sortAnnotationsBy = sortAnnotationsBy;
+ }
+
+ public boolean isShowAutocalculatedAbove()
+ {
+ return showAutocalculatedAbove;
+ }
+
+ public void setShowAutocalculatedAbove(boolean showAutocalculatedAbove)
+ {
+ this.showAutocalculatedAbove = showAutocalculatedAbove;
+ }
+
+ @Override
+ public boolean isScaleProteinAsCdna()
+ {
+ return viewStyle.isScaleProteinAsCdna();
+ }
+
+ @Override
+ public void setScaleProteinAsCdna(boolean b)
+ {
+ viewStyle.setScaleProteinAsCdna(b);
+ }
+
+ @Override
+ public boolean isProteinFontAsCdna()
+ {
+ return viewStyle.isProteinFontAsCdna();
+ }
+
+ @Override
+ public void setProteinFontAsCdna(boolean b)
+ {
+ viewStyle.setProteinFontAsCdna(b);
+ }
+
+ @Override
+ public void setShowComplementFeatures(boolean b)
+ {
+ viewStyle.setShowComplementFeatures(b);
+ }
+
+ @Override
+ public boolean isShowComplementFeatures()
+ {
+ return viewStyle.isShowComplementFeatures();
+ }
+
+ @Override
+ public void setShowComplementFeaturesOnTop(boolean b)
+ {
+ viewStyle.setShowComplementFeaturesOnTop(b);
+ }
+
+ @Override
+ public boolean isShowComplementFeaturesOnTop()
+ {
+ return viewStyle.isShowComplementFeaturesOnTop();
+ }
+
+ /**
+ * @return true if view should scroll to show the highlighted region of a
+ * sequence
+ * @return
+ */
+ @Override
+ public final boolean isFollowHighlight()
+ {
+ return followHighlight;
+ }
+
+ @Override
+ public final void setFollowHighlight(boolean b)
+ {
+ this.followHighlight = b;
+ }
+
+ @Override
+ public ViewportRanges getRanges()
+ {
+ return ranges;
+ }
+
+ /**
+ * 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(SearchResultsI sr)
+ {
+ final AlignViewportI complement = getCodingComplement();
+ if (complement == null || !complement.isFollowHighlight())
{
- updateStrucConsensus(ap);
+ return 0;
+ }
+ boolean iAmProtein = !getAlignment().isNucleotide();
+ AlignmentI proteinAlignment = iAmProtein ? getAlignment()
+ : complement.getAlignment();
+ if (proteinAlignment == null)
+ {
+ return 0;
}
+ final List<AlignedCodonFrame> mappings = proteinAlignment
+ .getCodonFrames();
- // Reset endRes of groups if beyond alignment width
- int alWidth = alignment.getWidth();
- List<SequenceGroup> groups = alignment.getGroups();
- if (groups != null)
+ /*
+ * 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 = ranges.getStartRes()
+ + (ranges.getEndRes() - ranges.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;
+ List<AlignedCodonFrame> seqMappings = null;
+ for (int seqNo = ranges
+ .getStartSeq(); seqNo <= lastSeq; seqNo++, seqOffset++)
{
- for (SequenceGroup sg : groups)
+ sequence = getAlignment().getSequenceAt(seqNo);
+ if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
{
- if (sg.getEndRes() > alWidth)
- {
- sg.setEndRes(alWidth - 1);
- }
+ continue;
+ }
+ if (Comparison.isGap(sequence.getCharAt(middleColumn)))
+ {
+ continue;
+ }
+ seqMappings = MappingUtils.findMappingsForSequenceAndOthers(sequence,
+ mappings,
+ getCodingComplement().getAlignment().getSequences());
+ if (!seqMappings.isEmpty())
+ {
+ break;
}
}
- if (selectionGroup != null && selectionGroup.getEndRes() > alWidth)
+ if (sequence == null || seqMappings == null || seqMappings.isEmpty())
{
- selectionGroup.setEndRes(alWidth - 1);
+ /*
+ * No ungapped mapped sequence in middle column - do nothing
+ */
+ return 0;
}
-
- resetAllColourSchemes();
- calculator.restartWorkers();
- // alignment.adjustSequenceAnnotations();
+ MappingUtils.addSearchResults(sr, sequence,
+ sequence.findPosition(middleColumn), seqMappings);
+ return seqOffset;
}
/**
- * reset scope and do calculations for all applied colourschemes on alignment
+ * synthesize a column selection if none exists so it covers the given
+ * selection group. if wholewidth is false, no column selection is made if the
+ * selection group covers the whole alignment width.
+ *
+ * @param sg
+ * @param wholewidth
*/
- void resetAllColourSchemes()
+ public void expandColSelection(SequenceGroup sg, boolean wholewidth)
{
- ColourSchemeI cs = globalColourScheme;
- if (cs != null)
+ int sgs, sge;
+ if (sg != null && (sgs = sg.getStartRes()) >= 0
+ && sg.getStartRes() <= (sge = sg.getEndRes())
+ && !this.hasSelectedColumns())
{
- cs.alignmentChanged(alignment, null);
-
- cs.setConsensus(hconsensus);
- if (cs.conservationApplied())
+ if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
{
- cs.setConservation(Conservation.calculateConservation("All",
- ResidueProperties.propHash, 3, alignment.getSequences(), 0,
- alignment.getWidth(), false, getConsPercGaps(), false));
+ // do nothing
+ return;
}
- }
-
- for (SequenceGroup sg : alignment.getGroups())
- {
- if (sg.cs != null)
+ if (colSel == null)
{
- sg.cs.alignmentChanged(sg, hiddenRepSequences);
+ colSel = new ColumnSelection();
+ }
+ for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
+ {
+ colSel.addElement(cspos);
}
- sg.recalcConservation();
}
}
- 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
+ /**
+ * hold status of current selection group - defined on alignment or not.
+ */
+ private boolean selectionIsDefinedGroup = false;
- if (hconsensus == null && !isDataset)
+ @Override
+ public boolean isSelectionDefinedGroup()
+ {
+ if (selectionGroup == null)
{
- if (!alignment.isNucleotide())
+ return false;
+ }
+ if (isSelectionGroupChanged(true))
+ {
+ selectionIsDefinedGroup = false;
+ List<SequenceGroup> gps = alignment.getGroups();
+ if (gps == null || gps.size() == 0)
{
- initConservation();
- initQuality();
+ selectionIsDefinedGroup = false;
}
else
{
- initRNAStructure();
+ selectionIsDefinedGroup = gps.contains(selectionGroup);
}
- initConsensus();
}
+ return selectionGroup.isDefined() || selectionIsDefinedGroup;
}
- private void initConsensus()
+ /**
+ * null, or currently highlighted results on this view
+ */
+ private SearchResultsI searchResults = null;
+
+ protected TreeModel currentTree = null;
+
+ @Override
+ public boolean hasSearchResults()
{
+ return searchResults != null;
+ }
- consensus = new AlignmentAnnotation("Consensus", "PID",
- new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
- consensus.hasText = true;
- consensus.autoCalculated = true;
+ @Override
+ public void setSearchResults(SearchResultsI results)
+ {
+ searchResults = results;
+ }
- if (showConsensus)
- {
- alignment.addAnnotation(consensus);
- }
+ @Override
+ public SearchResultsI getSearchResults()
+ {
+ return searchResults;
}
- private void initConservation()
+ /**
+ * get the consensus sequence as displayed under the PID consensus annotation
+ * row.
+ *
+ * @return consensus sequence as a new sequence object
+ */
+ public SequenceI getConsensusSeq()
{
- if (showConservation)
+ if (consensus == null)
{
- 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);
- }
+ updateConsensus(null);
}
- }
- private void initQuality()
- {
- if (showQuality)
+ if (consensus == null)
{
- if (quality == null)
+ return null;
+ }
+ StringBuffer seqs = new StringBuffer();
+ for (int i = 0; i < consensus.annotations.length; i++)
+ {
+ Annotation annotation = consensus.annotations[i];
+ if (annotation != 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);
+ String description = annotation.description;
+ if (description != null && description.startsWith("["))
+ {
+ // consensus is a tie - just pick the first one
+ seqs.append(description.charAt(1));
+ }
+ else
+ {
+ seqs.append(annotation.displayCharacter);
+ }
}
}
+
+ SequenceI sq = new Sequence("Consensus", seqs.toString());
+ sq.setDescription("Percentage Identity Consensus "
+ + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
+ return sq;
}
- private void initRNAStructure()
+
+ public boolean hasReferenceAnnotation()
{
- if (alignment.hasRNAStructure() && strucConsensus==null)
+ AlignmentAnnotation[] annots = this.alignment.getAlignmentAnnotation();
+ for (AlignmentAnnotation annot : annots)
{
- strucConsensus = new AlignmentAnnotation("StrucConsensus", "PID",
- new Annotation[1], 0f, 100f,
- AlignmentAnnotation.BAR_GRAPH);
- strucConsensus.hasText = true;
- strucConsensus.autoCalculated = true;
-
- if (showConsensus)
+ if ("RF".equals(annot.label) || annot.label.contains("Reference"))
{
- alignment.addAnnotation(strucConsensus);
+ return true;
}
}
+ return false;
}
- /*
- * (non-Javadoc)
- *
- * @see jalview.api.AlignViewportI#calcPanelHeight()
- */
- public int calcPanelHeight()
+ @Override
+ public void setCurrentTree(TreeModel tree)
{
- // setHeight of panels
- AlignmentAnnotation[] aa = getAlignment().getAlignmentAnnotation();
- int height = 0;
- int charHeight = getCharHeight();
- if (aa != null)
- {
- boolean graphgrp[] = null;
- 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 == null)
- {
- graphgrp = new boolean[aa.length];
- }
- if (graphgrp[aa[i].graphGroup])
- {
- continue;
- }
- else
- {
- graphgrp[aa[i].graphGroup] = true;
- }
- }
- aa[i].height = 0;
-
- if (aa[i].hasText)
- {
- aa[i].height += charHeight;
- }
+ currentTree = tree;
+ }
- if (aa[i].hasIcons)
- {
- aa[i].height += 16;
- }
+ @Override
+ public TreeModel getCurrentTree()
+ {
+ return currentTree;
+ }
- if (aa[i].graph > 0)
- {
- aa[i].height += aa[i].graphHeight;
- }
+ @Override
+ public AlignmentExportData getAlignExportData(AlignExportSettingsI options)
+ {
+ AlignmentI alignmentToExport = null;
+ String[] omitHidden = null;
+ alignmentToExport = null;
- if (aa[i].height == 0)
- {
- aa[i].height = 20;
- }
+ if (hasHiddenColumns() && !options.isExportHiddenColumns())
+ {
+ omitHidden = getViewAsString(false,
+ options.isExportHiddenSequences());
+ }
- height += aa[i].height;
- }
+ int[] alignmentStartEnd = new int[2];
+ if (hasHiddenRows() && options.isExportHiddenSequences())
+ {
+ alignmentToExport = getAlignment().getHiddenSequences()
+ .getFullAlignment();
}
- if (height == 0)
+ else
{
- // set minimum
- height = 20;
+ alignmentToExport = getAlignment();
}
- return height;
+ alignmentStartEnd = getAlignment().getHiddenColumns()
+ .getVisibleStartAndEndIndex(alignmentToExport.getWidth());
+ AlignmentExportData ed = new AlignmentExportData(alignmentToExport,
+ omitHidden, alignmentStartEnd);
+ return ed;
+ }
+
+ @Override
+ public boolean isNormaliseSequenceLogo()
+ {
+ return normaliseSequenceLogo;
+ }
+
+ public void setNormaliseSequenceLogo(boolean state)
+ {
+ normaliseSequenceLogo = state;
}
@Override
- public void updateGroupAnnotationSettings(boolean applyGlobalSettings,
- boolean preserveNewGroupSettings)
+ public boolean isNormaliseHMMSequenceLogo()
{
- boolean updateCalcs = false;
- boolean conv = isShowGroupConservation();
- boolean cons = isShowGroupConsensus();
- boolean showprf = isShowSequenceLogo();
- boolean showConsHist = isShowConsensusHistogram();
- boolean normLogo = isNormaliseSequenceLogo();
+ return hmmNormaliseSequenceLogo;
+ }
- /**
- * TODO reorder the annotation rows according to group/sequence ordering on
- * alignment
- */
- boolean sortg = true;
+ public void setNormaliseHMMSequenceLogo(boolean state)
+ {
+ hmmNormaliseSequenceLogo = state;
+ }
+ /**
+ * flag set to indicate if structure views might be out of sync with sequences
+ * in the alignment
+ */
- // remove old automatic annotation
- // add any new annotation
+ private boolean needToUpdateStructureViews = false;
- // intersect alignment annotation with alignment groups
+ @Override
+ public boolean isUpdateStructures()
+ {
+ return needToUpdateStructureViews;
+ }
- AlignmentAnnotation[] aan = alignment.getAlignmentAnnotation();
- List<SequenceGroup> oldrfs = new ArrayList<SequenceGroup>();
- if (aan != null)
+ @Override
+ public void setUpdateStructures(boolean update)
+ {
+ needToUpdateStructureViews = update;
+ }
+
+ @Override
+ public boolean needToUpdateStructureViews()
+ {
+ boolean update = needToUpdateStructureViews;
+ needToUpdateStructureViews = false;
+ return update;
+ }
+
+ @Override
+ public void addSequenceGroup(SequenceGroup sequenceGroup)
+ {
+ alignment.addGroup(sequenceGroup);
+
+ Color col = sequenceGroup.idColour;
+ if (col != null)
{
- for (int an = 0; an < aan.length; an++)
+ col = col.brighter();
+
+ for (SequenceI sq : sequenceGroup.getSequences())
{
- if (aan[an].autoCalculated && aan[an].groupRef != null)
- {
- oldrfs.add(aan[an].groupRef);
- alignment.deleteAnnotation(aan[an]);
- aan[an] = null;
- }
+ setSequenceColour(sq, col);
}
}
- if (alignment.getGroups() != null)
+
+ if (codingComplement != null)
{
- for (SequenceGroup sg : alignment.getGroups())
+ SequenceGroup mappedGroup = MappingUtils
+ .mapSequenceGroup(sequenceGroup, this, codingComplement);
+ if (mappedGroup.getSequences().size() > 0)
{
- 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)
+ codingComplement.getAlignment().addGroup(mappedGroup);
+
+ if (col != null)
{
- sg.recalcConservation();
+ for (SequenceI seq : mappedGroup.getSequences())
+ {
+ codingComplement.setSequenceColour(seq, col);
+ }
}
}
+ // propagate the structure view update flag according to our own setting
+ codingComplement.setUpdateStructures(needToUpdateStructureViews);
}
- oldrfs.clear();
+ }
+
+ @Override
+ public Iterator<int[]> getViewAsVisibleContigs(boolean selectedRegionOnly)
+ {
+ int start = 0;
+ int end = 0;
+ if (selectedRegionOnly && selectionGroup != null)
+ {
+ start = selectionGroup.getStartRes();
+ end = selectionGroup.getEndRes() + 1;
+ }
+ else
+ {
+ end = alignment.getWidth();
+ }
+ return (alignment.getHiddenColumns().getVisContigsIterator(start, end,
+ false));
}
/**
- * show the reference sequence in the alignment view
- */
- private boolean displayReferenceSeq=false;
- /**
- * colour according to the reference sequence defined on the alignment
+ * Filters out sequences with an eValue higher than the specified value. The
+ * filtered sequences are hidden or deleted. Sequences with no eValues are also
+ * filtered out.
+ *
+ * @param eValue
+ * @param delete
*/
- private boolean colourByReferenceSeq=false;
-
- public boolean isDisplayReferenceSeq()
+ public void filterByEvalue(double eValue)
{
- return alignment.hasSeqrep() && displayReferenceSeq;
+ for (SequenceI seq : alignment.getSequencesArray())
+ {
+ if ((seq.getAnnotation("Search Scores") == null
+ || seq.getAnnotation("Search Scores")[0].getEValue() > eValue)
+ && seq.getHMM() == null)
+ {
+ hideSequence(new SequenceI[] { seq });
+ }
+ }
}
- public void setDisplayReferenceSeq(boolean displayReferenceSeq)
+ /**
+ * Filters out sequences with an score lower than the specified value. The
+ * filtered sequences are hidden or deleted.
+ *
+ * @param score
+ * @param delete
+ */
+ public void filterByScore(double score)
{
- this.displayReferenceSeq = displayReferenceSeq;
- }
+ for (SequenceI seq : alignment.getSequencesArray())
+ {
+ if ((seq.getAnnotation("Search Scores") == null
+ || seq.getAnnotation("Search Scores")[0]
+ .getBitScore() < score)
+ && seq.getHMM() == null)
+ {
+ hideSequence(new SequenceI[] { seq });
+ }
+ }
+ }
- public boolean isColourByReferenceSeq()
+ /**
+ * Notify TreePanel and AlignmentPanel of some sort of alignment change.
+ */
+ public void notifyAlignment()
{
- return alignment.hasSeqrep() && colourByReferenceSeq;
+ changeSupport.firePropertyChange(PROPERTY_ALIGNMENT, null, alignment.getSequences());
}
-
- public void setColourByReferenceSeq(boolean colourByReferenceSeq)
+
+ /**
+ * Notify AlignmentPanel of a sequence column selection or visibility changes.
+ */
+ public void notifySequence()
{
- this.colourByReferenceSeq = colourByReferenceSeq;
+ changeSupport.firePropertyChange(PROPERTY_SEQUENCE, null, null);
}
-
}