+ return quality;
+ }
+
+ @Override
+ public AlignmentAnnotation getAlignmentConservationAnnotation()
+ {
+ return conservation;
+ }
+
+ @Override
+ public AlignmentAnnotation getAlignmentConsensusAnnotation()
+ {
+ return consensus;
+ }
+
+ @Override
+ public AlignmentAnnotation getComplementConsensusAnnotation()
+ {
+ return complementConsensus;
+ }
+
+ @Override
+ public AlignmentAnnotation getAlignmentStrucConsensusAnnotation()
+ {
+ return strucConsensus;
+ }
+
+ protected AlignCalcManagerI calculator = new AlignCalcManager();
+
+ /**
+ * trigger update of conservation annotation
+ */
+ public void updateConservation(final AlignmentViewPanel ap)
+ {
+ // see note in mantis : issue number 8585
+ if (alignment.isNucleotide() || conservation == null
+ || !autoCalculateConsensus)
+ {
+ return;
+ }
+ if (calculator
+ .getRegisteredWorkersOfClass(jalview.workers.ConservationThread.class) == null)
+ {
+ calculator.registerWorker(new jalview.workers.ConservationThread(
+ this, ap));
+ }
+ }
+
+ /**
+ * trigger update of consensus annotation
+ */
+ public void updateConsensus(final AlignmentViewPanel ap)
+ {
+ // see note in mantis : issue number 8585
+ if (consensus == null || !autoCalculateConsensus)
+ {
+ return;
+ }
+ if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null)
+ {
+ calculator.registerWorker(new ConsensusThread(this, ap));
+ }
+
+ /*
+ * A separate thread to compute cDNA consensus for a protein alignment
+ */
+ final AlignmentI al = this.getAlignment();
+ if (!al.isNucleotide() && al.getCodonFrames() != null
+ && !al.getCodonFrames().isEmpty())
+ {
+ if (calculator
+ .getRegisteredWorkersOfClass(ComplementConsensusThread.class) == null)
+ {
+ calculator.registerWorker(new ComplementConsensusThread(this, ap));
+ }
+ }
+ }
+
+ // --------START Structure Conservation
+ public void updateStrucConsensus(final AlignmentViewPanel ap)
+ {
+ if (autoCalculateStrucConsensus && strucConsensus == null
+ && alignment.isNucleotide() && alignment.hasRNAStructure())
+ {
+ // secondary structure has been added - so init the consensus line
+ initRNAStructure();
+ }
+
+ // see note in mantis : issue number 8585
+ if (strucConsensus == null || !autoCalculateStrucConsensus)
+ {
+ return;
+ }
+ if (calculator.getRegisteredWorkersOfClass(StrucConsensusThread.class) == null)
+ {
+ calculator.registerWorker(new StrucConsensusThread(this, ap));
+ }
+ }
+
+ public boolean isCalcInProgress()
+ {
+ return calculator.isWorking();
+ }
+
+ @Override
+ public boolean isCalculationInProgress(
+ AlignmentAnnotation alignmentAnnotation)
+ {
+ if (!alignmentAnnotation.autoCalculated)
+ {
+ return false;
+ }
+ if (calculator.workingInvolvedWith(alignmentAnnotation))
+ {
+ // System.err.println("grey out ("+alignmentAnnotation.label+")");
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isClosed()
+ {
+ // TODO: check that this isClosed is only true after panel is closed, not
+ // before it is fully constructed.
+ return alignment == null;
+ }
+
+ @Override
+ public AlignCalcManagerI getCalcManager()
+ {
+ return calculator;
+ }
+
+ /**
+ * should conservation rows be shown for groups
+ */
+ protected boolean showGroupConservation = false;
+
+ /**
+ * should consensus rows be shown for groups
+ */
+ protected boolean showGroupConsensus = false;
+
+ /**
+ * should consensus profile be rendered by default
+ */
+ protected boolean showSequenceLogo = false;
+
+ /**
+ * should consensus profile be rendered normalised to row height
+ */
+ protected boolean normaliseSequenceLogo = false;
+
+ /**
+ * should consensus histograms be rendered by default
+ */
+ protected boolean showConsensusHistogram = true;
+
+ /**
+ * @return the showConsensusProfile
+ */
+ @Override
+ public boolean isShowSequenceLogo()
+ {
+ return showSequenceLogo;
+ }
+
+ /**
+ * @param showSequenceLogo
+ * the new value
+ */
+ public void setShowSequenceLogo(boolean showSequenceLogo)
+ {
+ if (showSequenceLogo != this.showSequenceLogo)
+ {
+ // TODO: decouple settings setting from calculation when refactoring
+ // annotation update method from alignframe to viewport
+ this.showSequenceLogo = showSequenceLogo;
+ calculator.updateAnnotationFor(ConsensusThread.class);
+ calculator.updateAnnotationFor(ComplementConsensusThread.class);
+ calculator.updateAnnotationFor(StrucConsensusThread.class);
+ }
+ this.showSequenceLogo = showSequenceLogo;
+ }
+
+ /**
+ * @param showConsensusHistogram
+ * the showConsensusHistogram to set
+ */
+ public void setShowConsensusHistogram(boolean showConsensusHistogram)
+ {
+ this.showConsensusHistogram = showConsensusHistogram;
+ }
+
+ /**
+ * @return the showGroupConservation
+ */
+ public boolean isShowGroupConservation()
+ {
+ return showGroupConservation;
+ }
+
+ /**
+ * @param showGroupConservation
+ * the showGroupConservation to set
+ */
+ public void setShowGroupConservation(boolean showGroupConservation)
+ {
+ this.showGroupConservation = showGroupConservation;
+ }
+
+ /**
+ * @return the showGroupConsensus
+ */
+ public boolean isShowGroupConsensus()
+ {
+ return showGroupConsensus;
+ }
+
+ /**
+ * @param showGroupConsensus
+ * the showGroupConsensus to set
+ */
+ public void setShowGroupConsensus(boolean showGroupConsensus)
+ {
+ this.showGroupConsensus = showGroupConsensus;
+ }
+
+ /**
+ *
+ * @return flag to indicate if the consensus histogram should be rendered by
+ * default
+ */
+ @Override
+ public boolean isShowConsensusHistogram()
+ {
+ return this.showConsensusHistogram;
+ }
+
+ /**
+ * when set, updateAlignment will always ensure sequences are of equal length
+ */
+ private boolean padGaps = false;
+
+ /**
+ * when set, alignment should be reordered according to a newly opened tree
+ */
+ public boolean sortByTree = false;
+
+ /**
+ *
+ *
+ * @return null or the currently selected sequence region
+ */
+ @Override
+ public SequenceGroup getSelectionGroup()
+ {
+ return selectionGroup;
+ }
+
+ /**
+ * Set the selection group for this window.
+ *
+ * @param sg
+ * - group holding references to sequences in this alignment view
+ *
+ */
+ @Override
+ public void setSelectionGroup(SequenceGroup sg)
+ {
+ selectionGroup = sg;
+ }
+
+ public void setHiddenColumns(ColumnSelection colsel)
+ {
+ this.colSel = colsel;
+ }
+
+ @Override
+ public ColumnSelection getColumnSelection()
+ {
+ return colSel;
+ }
+
+ @Override
+ public void setColumnSelection(ColumnSelection colSel)
+ {
+ this.colSel = colSel;
+ if (colSel != null)
+ {
+ updateHiddenColumns();
+ }
+ }
+
+ /**
+ *
+ * @return
+ */
+ @Override
+ public Map<SequenceI, SequenceCollectionI> getHiddenRepSequences()
+ {
+ return hiddenRepSequences;
+ }
+
+ @Override
+ public void setHiddenRepSequences(
+ Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+ {
+ this.hiddenRepSequences = hiddenRepSequences;
+ }
+
+ @Override
+ public boolean hasHiddenColumns()
+ {
+ return colSel != null && colSel.hasHiddenColumns();
+ }
+
+ public void updateHiddenColumns()
+ {
+ // this method doesn't really do anything now. But - it could, since a
+ // column Selection could be in the process of modification
+ // hasHiddenColumns = colSel.hasHiddenColumns();
+ }
+
+ @Override
+ public boolean hasHiddenRows()
+ {
+ return alignment.getHiddenSequences().getSize() > 0;
+ }
+
+ protected SequenceGroup selectionGroup;
+
+ public void setSequenceSetId(String newid)
+ {
+ if (sequenceSetID != null)
+ {
+ System.err
+ .println("Warning - overwriting a sequenceSetId for a viewport!");
+ }
+ sequenceSetID = new String(newid);
+ }
+
+ @Override
+ public String getSequenceSetId()
+ {
+ if (sequenceSetID == null)
+ {
+ sequenceSetID = alignment.hashCode() + "";
+ }
+
+ return sequenceSetID;
+ }
+
+ /**
+ * unique viewId for synchronizing state (e.g. with stored Jalview Project)
+ *
+ */
+ protected String viewId = null;
+
+ @Override
+ public String getViewId()
+ {
+ if (viewId == null)
+ {
+ viewId = this.getSequenceSetId() + "." + this.hashCode() + "";
+ }
+ return viewId;
+ }
+
+ public void setIgnoreGapsConsensus(boolean b, AlignmentViewPanel ap)
+ {
+ ignoreGapsInConsensusCalculation = b;
+ if (ap != null)
+ {
+ updateConsensus(ap);
+ if (globalColourScheme != null)
+ {
+ globalColourScheme.setThreshold(globalColourScheme.getThreshold(),
+ ignoreGapsInConsensusCalculation);
+ }
+ }
+
+ }
+
+ private long sgrouphash = -1, colselhash = -1;
+
+ /**
+ * checks current SelectionGroup against record of last hash value, and
+ * updates record.
+ *
+ * @param b
+ * update the record of last hash value
+ *
+ * @return true if SelectionGroup changed since last call (when b is true)
+ */
+ public boolean isSelectionGroupChanged(boolean b)
+ {
+ int hc = (selectionGroup == null || selectionGroup.getSize() == 0) ? -1
+ : selectionGroup.hashCode();
+ if (hc != -1 && hc != sgrouphash)
+ {
+ if (b)
+ {
+ sgrouphash = hc;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * checks current colsel against record of last hash value, and optionally
+ * updates record.
+ *
+ * @param b
+ * update the record of last hash value
+ * @return true if colsel changed since last call (when b is true)
+ */
+ public boolean isColSelChanged(boolean b)
+ {
+ int hc = (colSel == null || colSel.size() == 0) ? -1 : colSel
+ .hashCode();
+ if (hc != -1 && hc != colselhash)
+ {
+ if (b)
+ {
+ colselhash = hc;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isIgnoreGapsConsensus()
+ {
+ return ignoreGapsInConsensusCalculation;
+ }
+
+ // / property change stuff
+
+ // JBPNote Prolly only need this in the applet version.
+ private final java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(
+ this);
+
+ protected boolean showConservation = true;
+
+ protected boolean showQuality = true;
+
+ protected boolean showConsensus = true;
+
+ private Map<SequenceI, Color> sequenceColours = new HashMap<SequenceI, Color>();
+
+ protected SequenceAnnotationOrder sortAnnotationsBy = null;
+
+ protected boolean showAutocalculatedAbove;
+
+ /**
+ * when set, view will scroll to show the highlighted position
+ */
+ private boolean followHighlight = true;
+
+ // TODO private with getters and setters?
+ public int startRes;
+
+ public int endRes;
+
+ public int startSeq;
+
+ public int endSeq;
+
+ /**
+ * Property change listener for changes in alignment
+ *
+ * @param listener
+ * DOCUMENT ME!
+ */
+ public void addPropertyChangeListener(
+ java.beans.PropertyChangeListener listener)
+ {
+ changeSupport.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param listener
+ * DOCUMENT ME!
+ */
+ public void removePropertyChangeListener(
+ java.beans.PropertyChangeListener listener)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Property change listener for changes in alignment
+ *
+ * @param prop
+ * DOCUMENT ME!
+ * @param oldvalue
+ * DOCUMENT ME!
+ * @param newvalue
+ * DOCUMENT ME!
+ */
+ public void firePropertyChange(String prop, Object oldvalue,
+ Object newvalue)
+ {
+ changeSupport.firePropertyChange(prop, oldvalue, newvalue);
+ }
+
+ // common hide/show column stuff
+
+ public void hideSelectedColumns()
+ {
+ if (colSel.size() < 1)
+ {
+ return;
+ }
+
+ colSel.hideSelectedColumns();
+ setSelectionGroup(null);
+
+ }
+
+ public void hideColumns(int start, int end)
+ {
+ if (start == end)
+ {
+ colSel.hideColumns(start);
+ }
+ else
+ {
+ colSel.hideColumns(start, end);
+ }
+ }
+
+ public void showColumn(int col)
+ {
+ colSel.revealHiddenColumns(col);
+
+ }
+
+ public void showAllHiddenColumns()
+ {
+ colSel.revealAllHiddenColumns();
+ }
+
+ // common hide/show seq stuff
+ public void showAllHiddenSeqs()
+ {
+ if (alignment.getHiddenSequences().getSize() > 0)
+ {
+ if (selectionGroup == null)
+ {
+ selectionGroup = new SequenceGroup();
+ selectionGroup.setEndRes(alignment.getWidth() - 1);
+ }
+ List<SequenceI> tmp = alignment.getHiddenSequences().showAll(
+ hiddenRepSequences);
+ for (SequenceI seq : tmp)
+ {
+ selectionGroup.addSequence(seq, false);
+ setSequenceAnnotationsVisible(seq, true);
+ }
+
+ hiddenRepSequences = null;
+
+ firePropertyChange("alignment", null, alignment.getSequences());
+ // used to set hasHiddenRows/hiddenRepSequences here, after the property
+ // changed event
+ sendSelection();
+ }
+ }
+
+ public void showSequence(int index)
+ {
+ List<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);
+ }
+ firePropertyChange("alignment", null, alignment.getSequences());
+ sendSelection();
+ }
+ }
+
+ public void hideAllSelectedSeqs()
+ {
+ if (selectionGroup == null || selectionGroup.getSize() < 1)
+ {
+ return;
+ }
+
+ SequenceI[] seqs = selectionGroup.getSequencesInOrder(alignment);
+
+ hideSequence(seqs);
+
+ setSelectionGroup(null);
+ }
+
+ public void hideSequence(SequenceI[] seq)
+ {
+ if (seq != null)
+ {
+ for (int i = 0; i < seq.length; i++)
+ {
+ alignment.getHiddenSequences().hideSequence(seq[i]);
+ setSequenceAnnotationsVisible(seq[i], false);
+ }
+ firePropertyChange("alignment", null, alignment.getSequences());
+ }
+ }
+
+ /**
+ * Set visibility for any annotations for the given sequence.
+ *
+ * @param sequenceI
+ */
+ protected void setSequenceAnnotationsVisible(SequenceI sequenceI,
+ boolean visible)
+ {
+ for (AlignmentAnnotation ann : alignment.getAlignmentAnnotation())
+ {
+ if (ann.sequenceRef == sequenceI)
+ {
+ ann.visible = visible;
+ }
+ }
+ }
+
+ public void hideRepSequences(SequenceI repSequence, SequenceGroup sg)
+ {
+ int sSize = sg.getSize();
+ if (sSize < 2)
+ {
+ return;
+ }
+
+ if (hiddenRepSequences == null)
+ {
+ hiddenRepSequences = new Hashtable();
+ }
+
+ hiddenRepSequences.put(repSequence, sg);
+
+ // Hide all sequences except the repSequence
+ SequenceI[] seqs = new SequenceI[sSize - 1];
+ int index = 0;
+ for (int i = 0; i < sSize; i++)
+ {
+ if (sg.getSequenceAt(i) != repSequence)
+ {
+ if (index == sSize - 1)
+ {
+ return;
+ }
+
+ seqs[index++] = sg.getSequenceAt(i);
+ }
+ }
+ sg.setSeqrep(repSequence); // note: not done in 2.7applet
+ sg.setHidereps(true); // note: not done in 2.7applet
+ hideSequence(seqs);
+
+ }
+
+ public boolean isHiddenRepSequence(SequenceI seq)
+ {
+ return alignment.getSeqrep() == seq
+ || (hiddenRepSequences != null && hiddenRepSequences
+ .containsKey(seq));
+ }
+
+ public SequenceGroup getRepresentedSequences(SequenceI seq)
+ {
+ return (SequenceGroup) (hiddenRepSequences == null ? null
+ : hiddenRepSequences.get(seq));
+ }
+
+ @Override
+ public int adjustForHiddenSeqs(int alignmentIndex)
+ {
+ return alignment.getHiddenSequences().adjustForHiddenSeqs(
+ alignmentIndex);
+ }
+
+ @Override
+ public void invertColumnSelection()
+ {
+ colSel.invertColumnSelection(0, alignment.getWidth());
+ }
+
+ @Override
+ public SequenceI[] getSelectionAsNewSequence()
+ {
+ SequenceI[] sequences;
+ // JBPNote: Need to test jalviewLite.getSelectedSequencesAsAlignmentFrom -
+ // this was the only caller in the applet for this method
+ // JBPNote: in applet, this method returned references to the alignment
+ // sequences, and it did not honour the presence/absence of annotation
+ // attached to the alignment (probably!)
+ if (selectionGroup == null || selectionGroup.getSize() == 0)
+ {
+ sequences = alignment.getSequencesArray();
+ AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation();
+ for (int i = 0; i < sequences.length; i++)