package jalview.api;
import jalview.analysis.Conservation;
+import jalview.analysis.TreeModel;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
-import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
+ import jalview.datamodel.ContactListI;
import jalview.datamodel.ProfilesI;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceCollectionI;
void clearSequenceColours();
/**
- * 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[]
- */
- CigarArray getViewAsCigars(boolean selectedRegionOnly);
-
- /**
* return a compact representation of the current alignment selection to pass
* to an analysis function
*
*/
SearchResultsI getSearchResults();
+ ContactListI getContactList(AlignmentAnnotation _aa, int column);
+
/**
* Updates view settings with the given font. You may need to call
* AlignmentPanel.fontChanged to update the layout geometry.
*/
@Override
void setProteinFontAsCdna(boolean b);
+
+ public abstract TreeModel getCurrentTree();
+
+ public abstract void setCurrentTree(TreeModel tree);
+
+ /**
+ * @param update
+ * - set the flag for updating structures on next repaint
+ */
+ void setUpdateStructures(boolean update);
+
+ /**
+ *
+ * @return true if structure views will be updated on next refresh
+ */
+ boolean isUpdateStructures();
+
+ /**
+ * check if structure views need to be updated, and clear the flag afterwards.
+ *
+ * @return if an update is needed
+ */
+ boolean needToUpdateStructureViews();
+
+ /**
+ * Adds sequencegroup to the alignment in the view. Also adds a group to the
+ * complement view if one is defined.
+ *
+ * @param sequenceGroup
+ * - a group defined on sequences in the alignment held by the view
+ */
+ void addSequenceGroup(SequenceGroup sequenceGroup);
}
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
-public class AnnotationPanel extends Panel implements AwtRenderPanelI,
- AdjustmentListener, ActionListener, MouseListener,
- MouseMotionListener, ViewportListenerI
+public class AnnotationPanel extends Panel
+ implements AwtRenderPanelI, AdjustmentListener, ActionListener,
+ MouseListener, MouseMotionListener, ViewportListenerI
{
AlignViewport av;
if (anot.length < av.getColumnSelection().getMax())
{
- Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
+ Annotation[] temp = new Annotation[av.getColumnSelection().getMax()
+ + 2];
System.arraycopy(anot, 0, temp, 0, anot.length);
anot = temp;
aa[activeRow].annotations = anot;
anot[index] = new Annotation(label, "", type, 0);
}
- anot[index].secondaryStructure = type != 'S' ? type : label
- .length() == 0 ? ' ' : label.charAt(0);
+ anot[index].secondaryStructure = type != 'S' ? type
+ : label.length() == 0 ? ' ' : label.charAt(0);
anot[index].displayCharacter = label;
}
}
{
activeRow = i;
}
- else if (aa[i].graph > 0)
+ else if (aa[i].graph != AlignmentAnnotation.NO_GRAPH)
{
// Stretch Graph
graphStretch = i;
}
}
- if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK
+ if ((evt.getModifiersEx()
+ & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK
&& activeRow != -1)
{
if (av.getColumnSelection() == null
{
if (graphStretch > -1)
{
- av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
- - evt.getY();
- if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
+ av.getAlignment()
+ .getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
+ - evt.getY();
+ if (av.getAlignment()
+ .getAlignmentAnnotation()[graphStretch].graphHeight < 0)
{
- av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
+ av.getAlignment()
+ .getAlignmentAnnotation()[graphStretch].graphHeight = 0;
}
graphStretchY = evt.getY();
av.calcPanelHeight();
needValidating = true;
- ap.paintAlignment(true);
+ // TODO: only update overview visible geometry
+ ap.paintAlignment(true, false);
}
else
{
if (av.hasHiddenColumns())
{
column = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(column);
+ .visibleToAbsoluteColumn(column);
}
if (row > -1 && column < aa[row].annotations.length
String name;
if (av.getAlignment().isNucleotide())
{
- name = ResidueProperties.nucleotideName.get(String
- .valueOf(residue));
- text.append(" Nucleotide: ").append(
- name != null ? name : residue);
+ name = ResidueProperties.nucleotideName
+ .get(String.valueOf(residue));
+ text.append(" Nucleotide: ")
+ .append(name != null ? name : residue);
}
else
{
- name = 'X' == residue ? "X" : ('*' == residue ? "STOP"
- : ResidueProperties.aa2Triplet.get(String
- .valueOf(residue)));
- text.append(" Residue: ").append(
- name != null ? name : residue);
+ name = 'X' == residue ? "X"
+ : ('*' == residue ? "STOP"
+ : ResidueProperties.aa2Triplet
+ .get(String.valueOf(residue)));
+ text.append(" Residue: ")
+ .append(name != null ? name : residue);
}
int residuePos = seqref.findPosition(column);
text.append(" (").append(residuePos).append(")");
gg.setColor(Color.white);
gg.fillRect(0, 0, getSize().width, getSize().height);
- drawComponent(gg, av.getRanges().getStartRes(), av.getRanges()
- .getEndRes() + 1);
+ drawComponent(gg, av.getRanges().getStartRes(),
+ av.getRanges().getEndRes() + 1);
g.drawImage(image, 0, 0, this);
}
public void fastPaint(int horizontal)
{
- if (horizontal == 0
+ if (horizontal == 0 || gg == null
|| av.getAlignment().getAlignmentAnnotation() == null
|| av.getAlignment().getAlignmentAnnotation().length < 1)
{
gg.copyArea(0, 0, imgWidth, getSize().height,
-horizontal * av.getCharWidth(), 0);
- int sr = av.getRanges().getStartRes(), er = av.getRanges().getEndRes() + 1, transX = 0;
+ int sr = av.getRanges().getStartRes(),
+ er = av.getRanges().getEndRes() + 1, transX = 0;
if (horizontal > 0) // scrollbar pulled right, image to the left
{
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
+ else if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ fastPaint(((int[]) evt.getNewValue())[0]
+ - ((int[]) evt.getOldValue())[0]);
+ }
+ else if (evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ repaint();
+ }
}
}
import jalview.util.MessageManager;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
import java.util.Collections;
import java.util.Enumeration;
+ import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
* @author JimP
*
*/
-public class Alignment implements AlignmentI
+public class Alignment implements AlignmentI, AutoCloseable
{
private Alignment dataset;
- protected List<SequenceI> sequences;
+ private List<SequenceI> sequences;
protected List<SequenceGroup> groups;
*/
public static AlignmentI createAlignment(CigarArray compactAlignment)
{
- throw new Error(
- MessageManager
- .getString("error.alignment_cigararray_not_implemented"));
+ throw new Error(MessageManager
+ .getString("error.alignment_cigararray_not_implemented"));
// this(compactAlignment.refCigars);
}
return AlignmentUtils.getSequencesByName(this);
}
-
@Override
public SequenceI getSequenceAt(int i)
{
return sequences.get(i);
}
}
+
return null;
}
}
@Override
- public void finalize() throws Throwable
+ public void close()
{
if (getDataset() != null)
{
- getDataset().removeAlignmentRef();
+ try
+ {
+ getDataset().removeAlignmentRef();
+ } catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
}
nullReferences();
- super.finalize();
}
/**
return;
}
// remove annotation very quickly
- AlignmentAnnotation[] t, todelete = new AlignmentAnnotation[annotations.length], tokeep = new AlignmentAnnotation[annotations.length];
+ AlignmentAnnotation[] t,
+ todelete = new AlignmentAnnotation[annotations.length],
+ tokeep = new AlignmentAnnotation[annotations.length];
int i, p, k;
if (gp == null)
{
sqname = sq.getName();
if (sqname.equals(token) // exact match
|| (b && // allow imperfect matches - case varies
- (sqname.equalsIgnoreCase(token))))
+ (sqname.equalsIgnoreCase(token))))
{
return getSequenceAt(i);
}
return -1;
}
-
@Override
public int getHeight()
{
public int getWidth()
{
int maxLength = -1;
-
+
for (int i = 0; i < sequences.size(); i++)
{
- if (getSequenceAt(i).getLength() > maxLength)
- {
- maxLength = getSequenceAt(i).getLength();
- }
+ maxLength = Math.max(maxLength, getSequenceAt(i).getLength());
}
return maxLength;
}
+ @Override
+ public int getVisibleWidth()
+ {
+ int w = getWidth();
+ if (hiddenCols != null)
+ {
+ w -= hiddenCols.getSize();
+ }
+ return w;
+ }
+
/**
* DOCUMENT ME!
*
}
if (dbr.getMap().getTo().getDatasetSequence() != null)
{
- throw new Error(
- "Implementation error: Map.getTo() for dbref " + dbr
- + " from " + curDs.getName()
- + " is not a dataset sequence.");
+ throw new Error("Implementation error: Map.getTo() for dbref "
+ + dbr + " from " + curDs.getName()
+ + " is not a dataset sequence.");
}
// we recurse to add all forward references to dataset sequences via
// DBRefs/etc
current = getSequenceAt(i);
// This should really be a sequence method
ends[i * 2] = current.findIndex(current.getStart());
- ends[i * 2 + 1] = current.findIndex(current.getStart()
- + current.getLength());
+ ends[i * 2 + 1] = current
+ .findIndex(current.getStart() + current.getLength());
boolean hitres = false;
for (int j = 0, rs = 0, ssiz = current.getLength(); j < ssiz; j++)
{
{
// TODO JAL-1270 needs test coverage
// currently tested for use in jalview.gui.SequenceFetcher
- boolean samegap = toappend.getGapCharacter() == getGapCharacter();
char oldc = toappend.getGapCharacter();
+ boolean samegap = oldc == getGapCharacter();
boolean hashidden = toappend.getHiddenSequences() != null
&& toappend.getHiddenSequences().hiddenSequences != null;
// get all sequences including any hidden ones
- List<SequenceI> sqs = (hashidden) ? toappend.getHiddenSequences()
- .getFullAlignment().getSequences() : toappend.getSequences();
+ List<SequenceI> sqs = (hashidden)
+ ? toappend.getHiddenSequences().getFullAlignment()
+ .getSequences()
+ : toappend.getSequences();
if (sqs != null)
{
// avoid self append deadlock by
{
if (!samegap)
{
- char[] oldseq = addedsq.getSequence();
- for (int c = 0; c < oldseq.length; c++)
- {
- if (oldseq[c] == oldc)
- {
- oldseq[c] = gapCharacter;
- }
- }
+ addedsq.replace(oldc, gapCharacter);
}
toappendsq.add(addedsq);
}
if (ourval instanceof String)
{
// append strings
- this.setProperty(k, ((String) ourval) + "; "
- + ((String) toapprop));
+ this.setProperty(k,
+ ((String) ourval) + "; " + ((String) toapprop));
}
else
{
AlignmentAnnotation annot = new AlignmentAnnotation(name, name,
new Annotation[1], 0f, 0f, AlignmentAnnotation.BAR_GRAPH);
annot.hasText = false;
- annot.setCalcId(new String(calcId));
+ if (calcId != null)
+ {
+ annot.setCalcId(new String(calcId));
+ }
annot.autoCalculated = autoCalc;
if (seqRef != null)
{
@Override
public Iterable<AlignmentAnnotation> findAnnotation(String calcId)
{
AlignmentAnnotation[] alignmentAnnotation = getAlignmentAnnotation();
if (alignmentAnnotation != null)
{
- for (AlignmentAnnotation a : alignmentAnnotation)
- {
- if (a.getCalcId() == calcId
- || (a.getCalcId() != null && calcId != null && a
- .getCalcId().equals(calcId)))
- {
- aa.add(a);
- }
- }
+ return AlignmentAnnotation.findAnnotation(
+ Arrays.asList(getAlignmentAnnotation()), calcId);
}
- return aa;
+ return Arrays.asList(new AlignmentAnnotation[] {});
}
@Override
public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label)
{
- ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
- for (AlignmentAnnotation ann : getAlignmentAnnotation())
- {
- if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId()
- .equals(calcId)))
- && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq))
- && (label == null || (ann.label != null && ann.label
- .equals(label))))
- {
- aa.add(ann);
- }
- }
- return aa;
+ return AlignmentAnnotation.findAnnotations(
+ Arrays.asList(getAlignmentAnnotation()), seq, calcId, label);
}
@Override
}
@Override
- public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols)
+ public boolean setHiddenColumns(HiddenColumns cols)
{
- boolean changed = cols == null ? hiddenCols != null
- : !cols.equals(hiddenCols);
- hiddenCols = cols;
- return changed;
- int[] alignmentStartEnd = new int[] { 0, getWidth() - 1 };
- int startPos = alignmentStartEnd[0];
- int endPos = alignmentStartEnd[1];
++ boolean changed = cols == null ? hiddenCols != null
++ : !cols.equals(hiddenCols);
++ hiddenCols = cols;
++ return changed;
+ }
-
+ @Override
+ public void setupJPredAlignment()
+ {
+ SequenceI repseq = getSequenceAt(0);
+ setSeqrep(repseq);
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideList(repseq.getInsertions());
+ setHiddenColumns(cs);
+ }
- int[] lowestRange = new int[] { -1, -1 };
- int[] higestRange = new int[] { -1, -1 };
+ @Override
+ public HiddenColumns propagateInsertions(SequenceI profileseq,
+ AlignmentView input)
+ {
+ int profsqpos = 0;
- for (int[] hiddenCol : hiddenCols)
- {
- lowestRange = (hiddenCol[0] <= startPos) ? hiddenCol : lowestRange;
- higestRange = (hiddenCol[1] >= endPos) ? hiddenCol : higestRange;
- }
+ char gc = getGapCharacter();
+ Object[] alandhidden = input.getAlignmentAndHiddenColumns(gc);
+ HiddenColumns nview = (HiddenColumns) alandhidden[1];
+ SequenceI origseq = ((SequenceI[]) alandhidden[0])[profsqpos];
+ return propagateInsertions(profileseq, origseq, nview);
+ }
- if (lowestRange[0] == -1 && lowestRange[1] == -1)
- {
- startPos = alignmentStartEnd[0];
- }
- else
+ /**
+ *
+ * @param profileseq
+ * sequence in al which corresponds to origseq
+ * @param al
+ * alignment which is to have gaps inserted into it
+ * @param origseq
+ * sequence corresponding to profileseq which defines gap map for
+ * modifying al
+ */
+ private HiddenColumns propagateInsertions(SequenceI profileseq,
+ SequenceI origseq, HiddenColumns hc)
+ {
+ // take the set of hidden columns, and the set of gaps in origseq,
+ // and remove all the hidden gaps from hiddenColumns
+
+ // first get the gaps as a Bitset
+ // then calculate hidden ^ not(gap)
+ BitSet gaps = origseq.gapBitset();
+ hc.andNot(gaps);
+
+ // for each sequence in the alignment, except the profile sequence,
+ // insert gaps corresponding to each hidden region but where each hidden
+ // column region is shifted backwards by the number of preceding visible
+ // gaps update hidden columns at the same time
+ HiddenColumns newhidden = new HiddenColumns();
+
+ int numGapsBefore = 0;
+ int gapPosition = 0;
+ Iterator<int[]> it = hc.iterator();
+ while (it.hasNext())
{
- startPos = lowestRange[1] + 1;
+ int[] region = it.next();
+
+ // get region coordinates accounting for gaps
+ // we can rely on gaps not being *in* hidden regions because we already
+ // removed those
+ while (gapPosition < region[0])
+ {
+ gapPosition++;
+ if (gaps.get(gapPosition))
+ {
+ numGapsBefore++;
+ }
+ }
+
+ int left = region[0] - numGapsBefore;
+ int right = region[1] - numGapsBefore;
+
+ newhidden.hideColumns(left, right);
+ padGaps(left, right, profileseq);
}
+ return newhidden;
+ }
+
+ /**
+ * Pad gaps in all sequences in alignment except profileseq
+ *
+ * @param left
+ * position of first gap to insert
+ * @param right
+ * position of last gap to insert
+ * @param profileseq
+ * sequence not to pad
+ */
+ private void padGaps(int left, int right, SequenceI profileseq)
+ {
+ char gc = getGapCharacter();
- if (higestRange[0] == -1 && higestRange[1] == -1)
+ // make a string with number of gaps = length of hidden region
+ StringBuilder sb = new StringBuilder();
+ for (int g = 0; g < right - left + 1; g++)
{
- endPos = alignmentStartEnd[1];
+ sb.append(gc);
}
- else
+
+ // loop over the sequences and pad with gaps where required
+ for (int s = 0, ns = getHeight(); s < ns; s++)
{
- endPos = higestRange[0] - 1;
+ SequenceI sqobj = getSequenceAt(s);
+ if ((sqobj != profileseq) && (sqobj.getLength() >= left))
+ {
+ String sq = sqobj.getSequenceAsString();
+ sqobj.setSequence(
+ sq.substring(0, left) + sb.toString() + sq.substring(left));
+ }
}
- return new int[] { startPos, endPos };
- }
- @Override
- public void setHiddenColumns(HiddenColumns cols)
- {
- hiddenCols = cols;
}
- Map<Object, ContactMatrixI> contactmaps = new HashMap<Object, ContactMatrixI>();
++ Map<Object, ContactMatrixI> contactmaps = new HashMap<>();
+ @Override
+ public
+ ContactListI getContactListFor(AlignmentAnnotation _aa, int column)
+ {
+ ContactMatrixI cm = contactmaps.get(_aa.annotationId);
+ if (cm == null)
+ {
+ return null;
+ }
+ return cm.getContactList(column);
+ }
+
+ @Override
+ public AlignmentAnnotation addContactList(ContactMatrixI cm)
+ {
+ Annotation _aa[] = new Annotation[getWidth()];
+ Annotation dummy = new Annotation(0.0f);
+ for (int i = 0; i < _aa.length; _aa[i++] = dummy)
+ {
+ ;
+ }
+ AlignmentAnnotation aa = new AlignmentAnnotation("Contact Matrix",
+ "Contact Matrix", _aa);
+ aa.graph = AlignmentAnnotation.CUSTOMRENDERER;
+ aa.graphMin = cm.getMin();
+ aa.graphMax = cm.getMax();
+ aa.editable = false;
+ // aa.autoCalculated = true;
+ contactmaps.put(aa.annotationId, cm);
+ addAnnotation(aa);
+ return aa;
+ }
}
import jalview.analysis.SecStrConsensus.SimpleBP;
import jalview.analysis.WUSSParseException;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
* Updates the _rnasecstr field Determines the positions that base pair and
* the positions of helices based on secondary structure from a Stockholm file
*
- * @param RNAannot
+ * @param rnaAnnotation
*/
- private void _updateRnaSecStr(CharSequence RNAannot)
+ private void _updateRnaSecStr(CharSequence rnaAnnotation)
{
try
{
- bps = Rna.getModeleBP(RNAannot);
- _rnasecstr = Rna.getBasePairs(bps);
+ _rnasecstr = Rna.getHelixMap(rnaAnnotation);
invalidrnastruc = -1;
} catch (WUSSParseException px)
{
{
return;
}
- Rna.HelixMap(_rnasecstr);
- // setRNAStruc(RNAannot);
if (_rnasecstr != null && _rnasecstr.length > 0)
{
}
/**
+ * Get the RNA Secondary Structure SequenceFeature Array if present
+ */
+ public SequenceFeature[] getRnaSecondaryStructure()
+ {
+ return this._rnasecstr;
+ }
+
+ /**
+ * Check the RNA Secondary Structure is equivalent to one in given
+ * AlignmentAnnotation param
+ */
+ public boolean rnaSecondaryStructureEquivalent(AlignmentAnnotation that)
+ {
+ return rnaSecondaryStructureEquivalent(that, true);
+ }
+
+ public boolean rnaSecondaryStructureEquivalent(AlignmentAnnotation that, boolean compareType)
+ {
+ SequenceFeature[] thisSfArray = this.getRnaSecondaryStructure();
+ SequenceFeature[] thatSfArray = that.getRnaSecondaryStructure();
+ if (thisSfArray == null || thatSfArray == null)
+ {
+ return thisSfArray == null && thatSfArray == null;
+ }
+ if (thisSfArray.length != thatSfArray.length)
+ {
+ return false;
+ }
+ Arrays.sort(thisSfArray, new SFSortByEnd()); // probably already sorted
+ // like this
+ Arrays.sort(thatSfArray, new SFSortByEnd()); // probably already sorted
+ // like this
+ for (int i=0; i < thisSfArray.length; i++) {
+ SequenceFeature thisSf = thisSfArray[i];
+ SequenceFeature thatSf = thatSfArray[i];
+ if (compareType) {
+ if (thisSf.getType() == null || thatSf.getType() == null) {
+ if (thisSf.getType() == null && thatSf.getType() == null) {
+ continue;
+ } else {
+ return false;
+ }
+ }
+ if (! thisSf.getType().equals(thatSf.getType())) {
+ return false;
+ }
+ }
+ if (!(thisSf.getBegin() == thatSf.getBegin()
+ && thisSf.getEnd() == thatSf.getEnd()))
+ {
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+ /**
* map of positions in the associated annotation
*/
private Map<Integer, Annotation> sequenceMapping;
public static final int LINE_GRAPH = 2;
+ public static final int CUSTOMRENDERER = 4;
+
public boolean belowAlignment = true;
public SequenceGroup groupRef = null;
private boolean isrna;
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#finalize()
- */
- @Override
- protected void finalize() throws Throwable
- {
- sequenceRef = null;
- groupRef = null;
- super.finalize();
- }
-
public static int getGraphValueFromString(String string)
{
if (string.equalsIgnoreCase("BAR_GRAPH"))
}
}
- // JBPNote: what does this do ?
- public void ConcenStru(CharSequence RNAannot) throws WUSSParseException
- {
- bps = Rna.getModeleBP(RNAannot);
- }
-
/**
* Creates a new AlignmentAnnotation object.
*
char firstChar = 0;
for (int i = 0; i < annotations.length; i++)
{
+ // DEBUG System.out.println(i + ": " + annotations[i]);
if (annotations[i] == null)
{
continue;
if (annotations[i].secondaryStructure == 'H'
|| annotations[i].secondaryStructure == 'E')
{
+ // DEBUG System.out.println( "/H|E/ '" +
+ // annotations[i].secondaryStructure + "'");
hasIcons |= true;
}
else
// Check for RNA secondary structure
{
- // System.out.println(annotations[i].secondaryStructure);
+ // DEBUG System.out.println( "/else/ '" +
+ // annotations[i].secondaryStructure + "'");
// TODO: 2.8.2 should this ss symbol validation check be a function in
// RNA/ResidueProperties ?
if (annotations[i].secondaryStructure == '('
|| annotations[i].secondaryStructure == 'B'
|| annotations[i].secondaryStructure == 'C'
|| annotations[i].secondaryStructure == 'D'
- || annotations[i].secondaryStructure == 'E'
+ // || annotations[i].secondaryStructure == 'E' // ambiguous on
+ // its own -- already checked above
|| annotations[i].secondaryStructure == 'F'
|| annotations[i].secondaryStructure == 'G'
- || annotations[i].secondaryStructure == 'H'
+ // || annotations[i].secondaryStructure == 'H' // ambiguous on
+ // its own -- already checked above
|| annotations[i].secondaryStructure == 'I'
|| annotations[i].secondaryStructure == 'J'
|| annotations[i].secondaryStructure == 'K'
firstChar = annotations[i].displayCharacter.charAt(0);
// check to see if it looks like a sequence or is secondary structure
// labelling.
- if (annotations[i].secondaryStructure != ' '
- && !hasIcons
- &&
- // Uncomment to only catch case where
- // displayCharacter==secondary
- // Structure
- // to correctly redisplay SS annotation imported from Stockholm,
- // exported to JalviewXML and read back in again.
- // &&
- // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure
- firstChar != ' '
- && firstChar != '$'
- && firstChar != 0xCE
- && firstChar != '('
- && firstChar != '['
- && firstChar != '>'
- && firstChar != '{'
- && firstChar != 'A'
- && firstChar != 'B'
- && firstChar != 'C'
- && firstChar != 'D'
- && firstChar != 'E'
- && firstChar != 'F'
- && firstChar != 'G'
- && firstChar != 'H'
- && firstChar != 'I'
- && firstChar != 'J'
- && firstChar != 'K'
- && firstChar != 'L'
- && firstChar != 'M'
- && firstChar != 'N'
- && firstChar != 'O'
- && firstChar != 'P'
- && firstChar != 'Q'
- && firstChar != 'R'
- && firstChar != 'S'
- && firstChar != 'T'
- && firstChar != 'U'
- && firstChar != 'V'
- && firstChar != 'W'
- && firstChar != 'X'
- && firstChar != 'Y'
- && firstChar != 'Z'
+ if (annotations[i].secondaryStructure != ' ' && !hasIcons &&
+ // Uncomment to only catch case where
+ // displayCharacter==secondary
+ // Structure
+ // to correctly redisplay SS annotation imported from Stockholm,
+ // exported to JalviewXML and read back in again.
+ // &&
+ // annotations[i].displayCharacter.charAt(0)==annotations[i].secondaryStructure
+ firstChar != ' ' && firstChar != '$' && firstChar != 0xCE
+ && firstChar != '(' && firstChar != '[' && firstChar != '<'
+ && firstChar != '{' && firstChar != 'A' && firstChar != 'B'
+ && firstChar != 'C' && firstChar != 'D' && firstChar != 'E'
+ && firstChar != 'F' && firstChar != 'G' && firstChar != 'H'
+ && firstChar != 'I' && firstChar != 'J' && firstChar != 'K'
+ && firstChar != 'L' && firstChar != 'M' && firstChar != 'N'
+ && firstChar != 'O' && firstChar != 'P' && firstChar != 'Q'
+ && firstChar != 'R' && firstChar != 'S' && firstChar != 'T'
+ && firstChar != 'U' && firstChar != 'V' && firstChar != 'W'
+ && firstChar != 'X' && firstChar != 'Y' && firstChar != 'Z'
&& firstChar != '-'
&& firstChar < jalview.schemes.ResidueProperties.aaIndex.length)
{
{
return ((index + offset < 0) || (index + offset) >= max
|| annotations[index + offset] == null
- || (annotations[index + offset].secondaryStructure <= ' ') ? ' '
- : annotations[index + offset].displayCharacter == null
- || annotations[index + offset].displayCharacter
- .length() == 0 ? annotations[index + offset].secondaryStructure
- : annotations[index + offset].displayCharacter
- .charAt(0));
+ || (annotations[index + offset].secondaryStructure <= ' ')
+ ? ' '
+ : annotations[index + offset].displayCharacter == null
+ || annotations[index
+ + offset].displayCharacter
+ .length() == 0
+ ? annotations[index
+ + offset].secondaryStructure
+ : annotations[index
+ + offset].displayCharacter
+ .charAt(0));
}
@Override
for (int i = offset; i < mx; i++)
{
- string[i] = (annotations[i] == null || (annotations[i].secondaryStructure <= 32)) ? ' '
- : (annotations[i].displayCharacter == null
- || annotations[i].displayCharacter.length() == 0 ? annotations[i].secondaryStructure
- : annotations[i].displayCharacter.charAt(0));
+ string[i] = (annotations[i] == null
+ || (annotations[i].secondaryStructure <= 32))
+ ? ' '
+ : (annotations[i].displayCharacter == null
+ || annotations[i].displayCharacter
+ .length() == 0
+ ? annotations[i].secondaryStructure
+ : annotations[i].displayCharacter
+ .charAt(0));
}
return new String(string);
}
this.calcId = annotation.calcId;
if (annotation.properties != null)
{
- properties = new HashMap<String, String>();
+ properties = new HashMap<>();
for (Map.Entry<String, String> val : annotation.properties.entrySet())
{
properties.put(val.getKey(), val.getValue());
if (annotation.sequenceMapping != null)
{
Integer p = null;
- sequenceMapping = new HashMap<Integer, Annotation>();
+ sequenceMapping = new HashMap<>();
Iterator<Integer> pos = annotation.sequenceMapping.keySet()
.iterator();
while (pos.hasNext())
Annotation[] temp = new Annotation[endRes - startRes + 1];
if (startRes < annotations.length)
{
- System.arraycopy(annotations, startRes, temp, 0, endRes - startRes
- + 1);
+ System.arraycopy(annotations, startRes, temp, 0,
+ endRes - startRes + 1);
}
if (sequenceRef != null)
{
int epos = sequenceRef.findPosition(endRes);
if (sequenceMapping != null)
{
- Map<Integer, Annotation> newmapping = new HashMap<Integer, Annotation>();
+ Map<Integer, Annotation> newmapping = new HashMap<>();
Iterator<Integer> e = sequenceMapping.keySet().iterator();
while (e.hasNext())
{
{
return;
}
- sequenceMapping = new HashMap<Integer, Annotation>();
+ sequenceMapping = new HashMap<>();
int seqPos;
seqPos = i + startRes;
}
- sequenceMapping.put(new Integer(seqPos), annotations[i]);
+ sequenceMapping.put(Integer.valueOf(seqPos), annotations[i]);
}
}
{
for (a = sequenceRef.getStart(); a <= sequenceRef.getEnd(); a++)
{
- index = new Integer(a);
+ index = Integer.valueOf(a);
Annotation annot = sequenceMapping.get(index);
if (annot != null)
{
{
if (i + 1 < iSize)
{
- System.arraycopy(annotations, i + 1, annotations, i, iSize - i
- - 1);
+ System.arraycopy(annotations, i + 1, annotations, i,
+ iSize - i - 1);
}
iSize--;
}
{
if (sequenceRef != null)
{
- boolean rIsDs = sequenceRef.getDatasetSequence() == null, tIsDs = sequenceI
- .getDatasetSequence() == null;
+ boolean rIsDs = sequenceRef.getDatasetSequence() == null,
+ tIsDs = sequenceI.getDatasetSequence() == null;
if (sequenceRef != sequenceI
- && (rIsDs && !tIsDs && sequenceRef != sequenceI
- .getDatasetSequence())
- && (!rIsDs && tIsDs && sequenceRef.getDatasetSequence() != sequenceI)
- && (!rIsDs && !tIsDs && sequenceRef.getDatasetSequence() != sequenceI
- .getDatasetSequence())
+ && (rIsDs && !tIsDs
+ && sequenceRef != sequenceI.getDatasetSequence())
+ && (!rIsDs && tIsDs
+ && sequenceRef.getDatasetSequence() != sequenceI)
+ && (!rIsDs && !tIsDs
+ && sequenceRef.getDatasetSequence() != sequenceI
+ .getDatasetSequence())
&& !sequenceRef.equals(sequenceI))
{
// if sequenceRef isn't intersecting with sequenceI
{
return;
}
- hidden.makeVisibleAnnotation(this);
+ makeVisibleAnnotation(hidden);
}
public void setPadGaps(boolean padgaps, char gapchar)
/**
* properties associated with the calcId
*/
- protected Map<String, String> properties = new HashMap<String, String>();
+ protected Map<String, String> properties = new HashMap<>();
/**
* base colour for line graphs. If null, will be set automatically by
throw new Error(
"liftOver currently not implemented for transfer of annotation between different types of seqeunce");
}
- boolean mapIsTo = (sp2sq != null) ? (sp2sq.getTo() == sq || sp2sq
- .getTo() == sq.getDatasetSequence()) : false;
+ boolean mapIsTo = (sp2sq != null)
+ ? (sp2sq.getTo() == sq
+ || sp2sq.getTo() == sq.getDatasetSequence())
+ : false;
// TODO build a better annotation element map and get rid of annotations[]
- Map<Integer, Annotation> mapForsq = new HashMap<Integer, Annotation>();
+ Map<Integer, Annotation> mapForsq = new HashMap<>();
if (sequenceMapping != null)
{
if (sp2sq != null)
{
for (Entry<Integer, Annotation> ie : sequenceMapping.entrySet())
{
- Integer mpos = Integer.valueOf(mapIsTo ? sp2sq
- .getMappedPosition(ie.getKey()) : sp2sq.getPosition(ie
- .getKey()));
+ Integer mpos = Integer
+ .valueOf(mapIsTo ? sp2sq.getMappedPosition(ie.getKey())
+ : sp2sq.getPosition(ie.getKey()));
if (mpos >= sq.getStart() && mpos <= sq.getEnd())
{
mapForsq.put(mpos, ie.getValue());
if (mapping != null)
{
Map<Integer, Annotation> old = sequenceMapping;
- Map<Integer, Annotation> remap = new HashMap<Integer, Annotation>();
+ Map<Integer, Annotation> remap = new HashMap<>();
int index = -1;
for (int mp[] : mapping.values())
{
{
if (properties == null)
{
- properties = new HashMap<String, String>();
+ properties = new HashMap<>();
}
properties.put(property, value);
}
* up to and excluding the target column; if the count is less
* than 1, the opening bracket is unmatched, so return its match
*/
- String closer = String.valueOf(Rna
- .getMatchingClosingParenthesis(symbol));
+ String closer = String
+ .valueOf(Rna.getMatchingClosingParenthesis(symbol));
String opener = String.valueOf(symbol);
int count = 0;
for (int j = col + 1; j < column; j++)
{
return graphMin < graphMax;
}
+
+ /**
+ * delete any columns in alignmentAnnotation that are hidden (including
+ * sequence associated annotation).
+ *
+ * @param hiddenColumns
+ * the set of hidden columns
+ */
+ public void makeVisibleAnnotation(HiddenColumns hiddenColumns)
+ {
+ if (annotations != null)
+ {
+ makeVisibleAnnotation(0, annotations.length, hiddenColumns);
+ }
+ }
+
+ /**
+ * delete any columns in alignmentAnnotation that are hidden (including
+ * sequence associated annotation).
+ *
+ * @param start
+ * remove any annotation to the right of this column
+ * @param end
+ * remove any annotation to the left of this column
+ * @param hiddenColumns
+ * the set of hidden columns
+ */
+ public void makeVisibleAnnotation(int start, int end,
+ HiddenColumns hiddenColumns)
+ {
+ if (annotations != null)
+ {
+ if (hiddenColumns.hasHiddenColumns())
+ {
+ removeHiddenAnnotation(start, end, hiddenColumns);
+ }
+ else
+ {
+ restrict(start, end);
+ }
+ }
+ }
+
+ /**
+ * The actual implementation of deleting hidden annotation columns
+ *
+ * @param start
+ * remove any annotation to the right of this column
+ * @param end
+ * remove any annotation to the left of this column
+ * @param hiddenColumns
+ * the set of hidden columns
+ */
+ private void removeHiddenAnnotation(int start, int end,
+ HiddenColumns hiddenColumns)
+ {
+ // mangle the alignmentAnnotation annotation array
+ ArrayList<Annotation[]> annels = new ArrayList<>();
+ Annotation[] els = null;
+
+ int w = 0;
+
+ Iterator<int[]> blocks = hiddenColumns.getVisContigsIterator(start,
+ end + 1, false);
+
+ int copylength;
+ int annotationLength;
+ while (blocks.hasNext())
+ {
+ int[] block = blocks.next();
+ annotationLength = block[1] - block[0] + 1;
+
+ if (blocks.hasNext())
+ {
+ // copy just the visible segment of the annotation row
+ copylength = annotationLength;
+ }
+ else
+ {
+ if (annotationLength + block[0] <= annotations.length)
+ {
+ // copy just the visible segment of the annotation row
+ copylength = annotationLength;
+ }
+ else
+ {
+ // copy to the end of the annotation row
+ copylength = annotations.length - block[0];
+ }
+ }
+
+ els = new Annotation[annotationLength];
+ annels.add(els);
+ System.arraycopy(annotations, block[0], els, 0, copylength);
+ w += annotationLength;
+ }
+
+ if (w != 0)
+ {
+ annotations = new Annotation[w];
+
+ w = 0;
+ for (Annotation[] chnk : annels)
+ {
+ System.arraycopy(chnk, 0, annotations, w, chnk.length);
+ w += chnk.length;
+ }
+ }
+ }
+
+ public static Iterable<AlignmentAnnotation> findAnnotations(
+ Iterable<AlignmentAnnotation> list, SequenceI seq, String calcId,
+ String label)
+ {
+
+ ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
+ for (AlignmentAnnotation ann : list)
+ {
+ if ((calcId == null || (ann.getCalcId() != null
+ && ann.getCalcId().equals(calcId)))
+ && (seq == null || (ann.sequenceRef != null
+ && ann.sequenceRef == seq))
+ && (label == null
+ || (ann.label != null && ann.label.equals(label))))
+ {
+ aa.add(ann);
+ }
+ }
+ return aa;
+ }
+
+ /**
+ * Answer true if any annotation matches the calcId passed in (if not null).
+ *
+ * @param list
+ * annotation to search
+ * @param calcId
+ * @return
+ */
+ public static boolean hasAnnotation(List<AlignmentAnnotation> list,
+ String calcId)
+ {
+
+ if (calcId != null && !"".equals(calcId))
+ {
+ for (AlignmentAnnotation a : list)
+ {
+ if (a.getCalcId() == calcId)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static Iterable<AlignmentAnnotation> findAnnotation(
+ List<AlignmentAnnotation> list, String calcId)
+ {
+
+ List<AlignmentAnnotation> aa = new ArrayList<>();
+ if (calcId == null)
+ {
+ return aa;
+ }
+ for (AlignmentAnnotation a : list)
+ {
+
+ if (a.getCalcId() == calcId || (a.getCalcId() != null
+ && calcId != null && a.getCalcId().equals(calcId)))
+ {
+ aa.add(a);
+ }
+ }
+ return aa;
+ }
+
}
* 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 License
+ * 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.
*
* 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 License for more details.
+ * PURPOSE. See the GNU General Public License for more details.
*
- * You should have received a copy of the GNU General License
+ * 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.
*/
/**
*
- * Calculates the maximum width of the alignment, including gaps.
+ * Answers the width of the alignment, including gaps, that is, the length of
+ * the longest sequence, or -1 if there are no sequences. Avoid calling this
+ * method repeatedly where possible, as it has to perform a calculation. Note
+ * that this width includes any hidden columns.
*
- * @return Greatest sequence length within alignment, or -1 if no sequences
- * present
+ * @return
+ * @see AlignmentI#getVisibleWidth()
*/
@Override
int getWidth();
/**
+ *
+ * Answers the visible width of the alignment, including gaps, that is, the
+ * length of the longest sequence, excluding any hidden columns. Answers -1 if
+ * there are no sequences. Avoid calling this method repeatedly where
+ * possible, as it has to perform a calculation.
+ *
+ * @return
+ */
+ int getVisibleWidth();
+
+ /**
* Calculates if this set of sequences (visible and invisible) are all the
* same length
*
AlignedCodonFrame getMapping(SequenceI mapFrom, SequenceI mapTo);
/**
- * Calculate the visible start and end index of an alignment. The result is
- * returned an int array where: int[0] = startIndex, and int[1] = endIndex.
+ * Set the hidden columns collection on the alignment. Answers true if the
+ * hidden column selection changed, else false.
*
- * @param hiddenCols
+ * @param cols
* @return
*/
- public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols);
+ public boolean setHiddenColumns(HiddenColumns cols);
+
+ /**
+ * Set the first sequence as representative and hide its insertions. Typically
+ * used when loading JPred files.
+ */
+ public void setupJPredAlignment();
+
+ /**
+ * Add gaps into the sequences aligned to profileseq under the given
+ * AlignmentView
+ *
+ * @param profileseq
+ * sequence in al which sequences are aligned to
+ * @param input
+ * alignment view where sequence corresponding to profileseq is first
+ * entry
+ * @return new HiddenColumns for new alignment view, with insertions into
+ * profileseq marked as hidden.
+ */
+ public HiddenColumns propagateInsertions(SequenceI profileseq,
+ AlignmentView input);
+ /**
+ * resolve a contact list instance (if any) associated with the annotation row
+ * and column position
+ *
+ * @param _aa
+ * @param column
+ * @return
+ */
+ ContactListI getContactListFor(AlignmentAnnotation _aa, int column);
+
+ AlignmentAnnotation addContactList(ContactMatrixI cm);
-
- public void setHiddenColumns(HiddenColumns cols);
}
package jalview.gui;
import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.HiddenColumns;
import jalview.schemes.ResidueProperties;
import jalview.util.Comparison;
import jalview.util.MessageManager;
+import jalview.util.Platform;
import jalview.viewmodel.ViewportListenerI;
import jalview.viewmodel.ViewportRanges;
MouseListener, MouseWheelListener, MouseMotionListener,
ActionListener, AdjustmentListener, Scrollable, ViewportListenerI
{
+ enum DragMode
+ {
+ Select, Resize, Undefined
+ };
+
String HELIX = MessageManager.getString("label.helix");
String SHEET = MessageManager.getString("label.sheet");
// Used For mouse Dragging and resizing graphs
int graphStretch = -1;
- int graphStretchY = -1;
+ int mouseDragLastX = -1;
- int min; // used by mouseDragged to see if user
+ int mouseDragLastY = -1;
- int max; // used by mouseDragged to see if user
+ DragMode dragMode = DragMode.Undefined;
boolean mouseDragging = false;
if (e.isShiftDown())
{
e.consume();
- if (e.getWheelRotation() > 0)
+ double wheelRotation = e.getPreciseWheelRotation();
+ if (wheelRotation > 0)
{
av.getRanges().scrollRight(true);
}
- else
+ else if (wheelRotation < 0)
{
av.getRanges().scrollRight(false);
}
@Override
public Dimension getPreferredScrollableViewportSize()
{
- return getPreferredSize();
+ Dimension ps = getPreferredSize();
+ return new Dimension(ps.width, adjustForAlignFrame(false, ps.height));
}
@Override
if (anot.length < av.getColumnSelection().getMax())
{
- Annotation[] temp = new Annotation[av.getColumnSelection().getMax() + 2];
+ Annotation[] temp = new Annotation[av.getColumnSelection().getMax()
+ + 2];
System.arraycopy(anot, 0, temp, 0, anot.length);
anot = temp;
aa[activeRow].annotations = anot;
anot[index] = new Annotation(label, "", type, 0);
}
- anot[index].secondaryStructure = type != 'S' ? type : label
- .length() == 0 ? ' ' : label.charAt(0);
+ anot[index].secondaryStructure = type != 'S' ? type
+ : label.length() == 0 ? ' ' : label.charAt(0);
anot[index].displayCharacter = label;
}
}
/**
- * DOCUMENT ME!
+ * Action on right mouse pressed on Mac is to show a pop-up menu for the
+ * annotation. Action on left mouse pressed is to find which annotation is
+ * pressed and mark the start of a column selection or graph resize operation.
*
* @param evt
- * DOCUMENT ME!
*/
@Override
public void mousePressed(MouseEvent evt)
{
return;
}
+ mouseDragLastX = evt.getX();
+ mouseDragLastY = evt.getY();
+ /*
+ * add visible annotation heights until we reach the y
+ * position, to find which annotation it is in
+ */
int height = 0;
activeRow = -1;
{
activeRow = i;
}
- else if (aa[i].graph > 0)
+ else if (aa[i].graph != 0)
{
- // Stretch Graph
+ /*
+ * we have clicked on a resizable graph annotation
+ */
graphStretch = i;
- graphStretchY = y;
}
-
break;
}
}
}
/**
- * DOCUMENT ME!
+ * Action on mouse up is to clear mouse drag data and call mouseReleased on
+ * ScalePanel, to deal with defining the selection group (if any) defined by
+ * the mouse drag
*
* @param evt
- * DOCUMENT ME!
*/
@Override
public void mouseReleased(MouseEvent evt)
{
graphStretch = -1;
- graphStretchY = -1;
+ mouseDragLastX = -1;
+ mouseDragLastY = -1;
mouseDragging = false;
+ dragMode = DragMode.Undefined;
ap.getScalePanel().mouseReleased(evt);
/*
@Override
public void mouseDragged(MouseEvent evt)
{
- if (graphStretch > -1)
+ /*
+ * todo: if dragMode is Undefined:
+ * - set to Select if dx > dy
+ * - set to Resize if dy > dx
+ * - do nothing if dx == dy
+ */
+ final int x = evt.getX();
+ final int y = evt.getY();
+ if (dragMode == DragMode.Undefined)
{
- av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight += graphStretchY
- - evt.getY();
- if (av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight < 0)
+ int dx = Math.abs(x - mouseDragLastX);
+ int dy = Math.abs(y - mouseDragLastY);
+ if (graphStretch == -1 || dx > dy)
{
- av.getAlignment().getAlignmentAnnotation()[graphStretch].graphHeight = 0;
+ /*
+ * mostly horizontal drag, or not a graph annotation
+ */
+ dragMode = DragMode.Select;
+ }
+ else if (dy > dx)
+ {
+ /*
+ * mostly vertical drag
+ */
+ dragMode = DragMode.Resize;
}
- graphStretchY = evt.getY();
- adjustPanelHeight();
- ap.paintAlignment(true);
}
- else
+
+ if (dragMode == DragMode.Undefined)
+ {
+ /*
+ * drag is diagonal - defer deciding whether to
+ * treat as up/down or left/right
+ */
+ return;
+ }
+
+ try
+ {
+ if (dragMode == DragMode.Resize)
+ {
+ /*
+ * resize graph annotation if mouse was dragged up or down
+ */
+ int deltaY = mouseDragLastY - evt.getY();
+ if (deltaY != 0)
+ {
+ AlignmentAnnotation graphAnnotation = av.getAlignment()
+ .getAlignmentAnnotation()[graphStretch];
+ int newHeight = Math.max(0, graphAnnotation.graphHeight + deltaY);
+ graphAnnotation.graphHeight = newHeight;
+ adjustPanelHeight();
+ ap.paintAlignment(false, false);
+ }
+ }
+ else
+ {
+ /*
+ * for mouse drag left or right, delegate to
+ * ScalePanel to adjust the column selection
+ */
+ ap.getScalePanel().mouseDragged(evt);
+ }
+ } finally
{
- ap.getScalePanel().mouseDragged(evt);
+ mouseDragLastX = x;
+ mouseDragLastY = y;
}
}
@Override
public void mouseMoved(MouseEvent evt)
{
+ int yPos = evt.getY();
AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
- if (aa == null)
- {
- this.setToolTipText(null);
- return;
- }
-
- int row = -1;
- int height = 0;
-
- for (int i = 0; i < aa.length; i++)
- {
- if (aa[i].visible)
- {
- height += aa[i].height;
- }
-
- if (evt.getY() < height)
- {
- row = i;
- break;
- }
- }
+ int row = getRowIndex(yPos, aa);
if (row == -1)
{
int column = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
+ column = Math.min(column, av.getRanges().getEndRes());
if (av.hasHiddenColumns())
{
column = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(column);
+ .visibleToAbsoluteColumn(column);
}
AlignmentAnnotation ann = aa[row];
if (row > -1 && ann.annotations != null
&& column < ann.annotations.length)
{
- buildToolTip(ann, column, aa);
- setStatusMessage(column, ann);
+ setToolTipText(buildToolTip(ann, column, aa));
+ String msg = getStatusMessage(av.getAlignment(), column, ann);
+ ap.alignFrame.setStatus(msg);
}
else
{
this.setToolTipText(null);
- ap.alignFrame.statusBar.setText(" ");
+ ap.alignFrame.setStatus(" ");
+ }
+ }
+
+ /**
+ * Answers the index in the annotations array of the visible annotation at the
+ * given y position. This is done by adding the heights of visible annotations
+ * until the y position has been exceeded. Answers -1 if no annotations are
+ * visible, or the y position is below all annotations.
+ *
+ * @param yPos
+ * @param aa
+ * @return
+ */
+ static int getRowIndex(int yPos, AlignmentAnnotation[] aa)
+ {
+ if (aa == null)
+ {
+ return -1;
}
+ int row = -1;
+ int height = 0;
+
+ for (int i = 0; i < aa.length; i++)
+ {
+ if (aa[i].visible)
+ {
+ height += aa[i].height;
+ }
+
+ if (height > yPos)
+ {
+ row = i;
+ break;
+ }
+ }
+ return row;
}
/**
- * Builds a tooltip for the annotation at the current mouse position.
+ * Answers a tooltip for the annotation at the current mouse position
*
* @param ann
* @param column
* @param anns
*/
- void buildToolTip(AlignmentAnnotation ann, int column,
+ static String buildToolTip(AlignmentAnnotation ann, int column,
AlignmentAnnotation[] anns)
{
+ String tooltip = null;
if (ann.graphGroup > -1)
{
StringBuilder tip = new StringBuilder(32);
if (tip.length() != 6)
{
tip.setLength(tip.length() - 4);
- this.setToolTipText(tip.toString() + "</html>");
+ tooltip = tip.toString() + "</html>";
}
}
- else if (ann.annotations[column] != null)
+ else if (column < ann.annotations.length
+ && ann.annotations[column] != null)
{
String description = ann.annotations[column].description;
if (description != null && description.length() > 0)
{
- this.setToolTipText(JvSwingUtils.wrapTooltip(true, description));
+ tooltip = JvSwingUtils.wrapTooltip(true, description);
+ }
+ else
+ {
+ tooltip = null; // no tooltip if null or empty description
}
}
else
{
// clear the tooltip.
- this.setToolTipText(null);
+ tooltip = null;
}
+ return tooltip;
}
/**
- * Constructs and displays the status bar message
+ * Constructs and returns the status bar message
*
+ * @param al
* @param column
* @param ann
*/
- void setStatusMessage(int column, AlignmentAnnotation ann)
+ static String getStatusMessage(AlignmentI al, int column,
+ AlignmentAnnotation ann)
{
/*
* show alignment column and annotation description if any
text.append(MessageManager.getString("label.column")).append(" ")
.append(column + 1);
- if (ann.annotations[column] != null)
+ if (column < ann.annotations.length && ann.annotations[column] != null)
{
String description = ann.annotations[column].description;
if (description != null && description.trim().length() > 0)
SequenceI seqref = ann.sequenceRef;
if (seqref != null)
{
- int seqIndex = av.getAlignment().findIndex(seqref);
+ int seqIndex = al.findIndex(seqref);
if (seqIndex != -1)
{
- text.append(", ")
- .append(MessageManager.getString("label.sequence"))
+ text.append(", ").append(MessageManager.getString("label.sequence"))
.append(" ").append(seqIndex + 1);
char residue = seqref.getCharAt(column);
if (!Comparison.isGap(residue))
{
text.append(" ");
String name;
- if (av.getAlignment().isNucleotide())
+ if (al.isNucleotide())
{
- name = ResidueProperties.nucleotideName.get(String
- .valueOf(residue));
- text.append(" Nucleotide: ").append(
- name != null ? name : residue);
+ name = ResidueProperties.nucleotideName
+ .get(String.valueOf(residue));
+ text.append(" Nucleotide: ")
+ .append(name != null ? name : residue);
}
else
{
- name = 'X' == residue ? "X" : ('*' == residue ? "STOP"
- : ResidueProperties.aa2Triplet.get(String
- .valueOf(residue)));
+ name = 'X' == residue ? "X"
+ : ('*' == residue ? "STOP"
+ : ResidueProperties.aa2Triplet
+ .get(String.valueOf(residue)));
text.append(" Residue: ").append(name != null ? name : residue);
}
int residuePos = seqref.findPosition(column);
}
}
- ap.alignFrame.statusBar.setText(text.toString());
+ return text.toString();
}
/**
@Override
public void paintComponent(Graphics g)
{
+ super.paintComponent(g);
+
g.setColor(Color.white);
g.fillRect(0, 0, getWidth(), getHeight());
return;
}
}
- imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes() + 1)
- * av.getCharWidth();
+ imgWidth = (av.getRanges().getEndRes() - av.getRanges().getStartRes()
+ + 1) * av.getCharWidth();
if (imgWidth < 1)
{
return;
{
try
{
- image = new BufferedImage(imgWidth, ap.getAnnotationPanel()
- .getHeight(), BufferedImage.TYPE_INT_RGB);
+ image = new BufferedImage(imgWidth,
+ ap.getAnnotationPanel().getHeight(),
+ BufferedImage.TYPE_INT_RGB);
} catch (OutOfMemoryError oom)
{
try
gg.fillRect(0, 0, imgWidth, image.getHeight());
imageFresh = true;
}
-
- drawComponent(gg, av.getRanges().getStartRes(), av.getRanges()
- .getEndRes() + 1);
+
+ drawComponent(gg, av.getRanges().getStartRes(),
+ av.getRanges().getEndRes() + 1);
imageFresh = false;
g.drawImage(image, 0, 0, this);
}
int er = av.getRanges().getEndRes() + 1;
int transX = 0;
- long stime = System.currentTimeMillis();
gg.copyArea(0, 0, imgWidth, getHeight(),
-horizontal * av.getCharWidth(), 0);
- long mtime = System.currentTimeMillis();
if (horizontal > 0) // scrollbar pulled right, image to the left
{
drawComponent(gg, sr, er);
gg.translate(-transX, 0);
- long dtime = System.currentTimeMillis();
+
fastPaint = true;
- repaint();
- long rtime = System.currentTimeMillis();
- if (debugRedraw)
- {
- System.err.println("Scroll:\t" + horizontal + "\tCopyArea:\t"
- + (mtime - stime) + "\tDraw component:\t" + (dtime - mtime)
- + "\tRepaint call:\t" + (rtime - dtime));
- }
+ // Call repaint on alignment panel so that repaints from other alignment
+ // panel components can be aggregated. Otherwise performance of the overview
+ // window and others may be adversely affected.
+ av.getAlignPanel().repaint();
}
private volatile boolean lastImageGood = false;
// and draw a faded image until the calculation
// has completed
if (lastImageGood
- && (fadedImage == null || fadedImage.getWidth() != imgWidth || fadedImage
- .getHeight() != image.getHeight()))
+ && (fadedImage == null || fadedImage.getWidth() != imgWidth
+ || fadedImage.getHeight() != image.getHeight()))
{
// System.err.println("redraw faded image ("+(fadedImage==null ?
// "null image" : "") + " lastGood="+lastImageGood+")");
fadedG.setColor(Color.white);
fadedG.fillRect(0, 0, imgWidth, image.getHeight());
- fadedG.setComposite(AlphaComposite.getInstance(
- AlphaComposite.SRC_OVER, .3f));
+ fadedG.setComposite(
+ AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .3f));
fadedG.drawImage(image, 0, 0, this);
}
return;
}
- lastImageGood = renderer.drawComponent(this, av, g, activeRow,
- startRes, endRes);
+ lastImageGood = renderer.drawComponent(this, av, g, activeRow, startRes,
+ endRes);
if (!lastImageGood && fadedImage == null)
{
fadedImage = oldFaded;
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
+ else if (evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ))
+ {
+ fastPaint(((int[]) evt.getNewValue())[0]
+ - ((int[]) evt.getOldValue())[0]);
+ }
+ else if (evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
+ {
+ repaint();
+ }
+ }
+
+ /**
+ * computes the visible height of the annotation panel
+ *
+ * @param adjustPanelHeight
+ * - when false, just adjust existing height according to other
+ * windows
+ * @param annotationHeight
+ * @return height to use for the ScrollerPreferredVisibleSize
+ */
+ public int adjustForAlignFrame(boolean adjustPanelHeight,
+ int annotationHeight)
+ {
+ /*
+ * Estimate available height in the AlignFrame for alignment +
+ * annotations. Deduct an estimate for title bar, menu bar, scale panel,
+ * hscroll, status bar, insets.
+ */
+ int stuff = (ap.getViewName() != null ? 30 : 0)
+ + (Platform.isAMac() ? 120 : 140);
+ int availableHeight = ap.alignFrame.getHeight() - stuff;
+ int rowHeight = av.getCharHeight();
+
+ if (adjustPanelHeight)
+ {
+ int alignmentHeight = rowHeight * av.getAlignment().getHeight();
+
+ /*
+ * If not enough vertical space, maximize annotation height while keeping
+ * at least two rows of alignment visible
+ */
+ if (annotationHeight + alignmentHeight > availableHeight)
+ {
+ annotationHeight = Math.min(annotationHeight,
+ availableHeight - 2 * rowHeight);
+ }
+ }
+ else
+ {
+ // maintain same window layout whilst updating sliders
+ annotationHeight = Math.min(ap.annotationScroller.getSize().height,
+ availableHeight - 2 * rowHeight);
+ }
+ return annotationHeight;
}
}
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
+ import jalview.datamodel.SeqDistanceContactMatrix;
import jalview.datamodel.PDBEntry.Type;
import jalview.datamodel.SequenceI;
import jalview.ext.jmol.JmolParser;
public static String getSupportedFormats()
{
return "Formats currently supported are\n"
- + prettyPrint(FileFormats.getInstance().getReadableFormats());
+ + prettyPrint(FileFormats.getInstance().getReadableFormats());
}
+
public AppletFormatAdapter()
{
}
String structureParser = StructureImportSettings
.getDefaultPDBFileParser();
boolean isParseWithJMOL = structureParser.equalsIgnoreCase(
- StructureImportSettings.StructureParser.JMOL_PARSER
- .toString());
+ StructureImportSettings.StructureParser.JMOL_PARSER
+ .toString());
StructureImportSettings.addSettings(annotFromStructure,
localSecondaryStruct, serviceSecondaryStruct);
if (isParseWithJMOL)
localSecondaryStruct, serviceSecondaryStruct, inFile,
sourceType);
}
- ((StructureFile) alignFile).setDbRefType(FileFormat.PDB
- .equals(fileFormat) ? Type.PDB : Type.MMCIF);
+ ((StructureFile) alignFile).setDbRefType(
+ FileFormat.PDB.equals(fileFormat) ? Type.PDB : Type.MMCIF);
}
else
{
// alignFile = fileFormat.getAlignmentFile(inFile, sourceType);
- alignFile = fileFormat.getReader(new FileParse(inFile,
- sourceType));
+ alignFile = fileFormat.getReader(new FileParse(inFile, sourceType));
}
return buildAlignmentFromFile();
} catch (Exception e)
{
e.printStackTrace();
- System.err.println("Failed to read alignment using the '"
- + fileFormat + "' reader.\n" + e);
+ System.err.println("Failed to read alignment using the '" + fileFormat
+ + "' reader.\n" + e);
if (e.getMessage() != null
&& e.getMessage().startsWith(INVALID_CHARACTERS))
alignFile.addGroups(al);
+ al.addContactList(new SeqDistanceContactMatrix(al.getWidth()));
+
return al;
}
AlignmentViewPanel ap, boolean selectedOnly)
{
- AlignmentView selvew = ap.getAlignViewport().getAlignmentView(
- selectedOnly, false);
- AlignmentI aselview = selvew.getVisibleAlignment(ap.getAlignViewport()
- .getGapCharacter());
+ AlignmentView selvew = ap.getAlignViewport()
+ .getAlignmentView(selectedOnly, false);
+ AlignmentI aselview = selvew
+ .getVisibleAlignment(ap.getAlignViewport().getGapCharacter());
List<AlignmentAnnotation> ala = (ap.getAlignViewport()
.getVisibleAlignmentAnnotation(selectedOnly));
if (ala != null)
} catch (Exception e)
{
System.err.println("Failed to write alignment as a '"
- + format.getName()
- + "' file\n");
+ + format.getName() + "' file\n");
e.printStackTrace();
}
System.gc();
long memf = -r.totalMemory() + r.freeMemory();
long t1 = -System.currentTimeMillis();
- AlignmentI al = afa
- .readFile(args[i], DataSourceType.FILE,
- new IdentifyFile().identify(args[i],
- DataSourceType.FILE));
+ AlignmentI al = afa.readFile(args[i], DataSourceType.FILE,
+ new IdentifyFile().identify(args[i],
+ DataSourceType.FILE));
t1 += System.currentTimeMillis();
System.gc();
memf += r.totalMemory() - r.freeMemory();
+ " sequences and " + al.getWidth() + " columns.");
try
{
- System.out.println(new AppletFormatAdapter().formatSequences(
- FileFormat.Fasta, al, true));
+ System.out.println(new AppletFormatAdapter()
+ .formatSequences(FileFormat.Fasta, al, true));
} catch (Exception e)
{
- System.err
- .println("Couln't format the alignment for output as a FASTA file.");
+ System.err.println(
+ "Couln't format the alignment for output as a FASTA file.");
e.printStackTrace(System.err);
}
}
System.out.println("Couldn't read alignment");
}
System.out.println("Read took " + (t1 / 1000.0) + " seconds.");
- System.out
- .println("Difference between free memory now and before is "
+ System.out.println(
+ "Difference between free memory now and before is "
+ (memf / (1024.0 * 1024.0) * 1.0) + " MB");
} catch (Exception e)
{
{
if (debug)
{
- System.out.println("Trying to get contents of resource as "
- + protocol + ":");
+ System.out.println(
+ "Trying to get contents of resource as " + protocol + ":");
}
fp = new FileParse(file, protocol);
if (!fp.isValid())
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.HiddenColumns;
import jalview.datamodel.ProfilesI;
+ import jalview.renderer.api.AnnotationRendererFactoryI;
+ import jalview.renderer.api.AnnotationRowRendererI;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.NucleotideColourScheme;
import jalview.schemes.ResidueProperties;
ResidueShaderI profcolour = null;
private ColumnSelection columnSelection;
-
+
private HiddenColumns hiddenColumns;
private ProfilesI hconsensus;
hStrucConsensus = null;
fadedImage = null;
annotationPanel = null;
+ rendererFactoryI = null;
}
void drawStemAnnot(Graphics g, Annotation[] row_annotations, int lastSSX,
boolean validRes, boolean validEnd)
{
g.setColor(STEM_COLOUR);
- int sCol = (lastSSX / charWidth) + startRes;
+ int sCol = (lastSSX / charWidth)
+ + hiddenColumns.visibleToAbsoluteColumn(startRes);
int x1 = lastSSX;
int x2 = (x * charWidth);
* display a backward arrow
*/
g.fillPolygon(new int[] { lastSSX + 5, lastSSX + 5, lastSSX },
- new int[] { y + iconOffset, y + 14 + iconOffset,
- y + 8 + iconOffset }, 3);
+ new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+ 3);
x1 += 5;
}
if (diffdownstream)
* if annotation ending with an opeing base pair half of the stem,
* display a forward arrow
*/
- g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 }, new int[] {
- y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
+ g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 },
+ new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+ 3);
x2 -= 5;
}
if (diffupstream)
// System.out.println(nonCanColor);
g.setColor(nonCanColor);
- int sCol = (lastSSX / charWidth) + startRes;
+ int sCol = (lastSSX / charWidth)
+ + hiddenColumns.visibleToAbsoluteColumn(startRes);
int x1 = lastSSX;
int x2 = (x * charWidth);
boolean diffdownstream = !validRes || !validEnd
|| row_annotations[column] == null
|| !dc.equals(row_annotations[column].displayCharacter);
- // System.out.println("Column "+column+" diff up: "+diffupstream+" down:"+diffdownstream);
+ // System.out.println("Column "+column+" diff up: "+diffupstream+"
+ // down:"+diffdownstream);
// If a closing base pair half of the stem, display a backward arrow
if (column > 0 && Rna.isClosingParenthesis(dc))
{
// dc.equals(row_annotations[column-2].displayCharacter))
{
g.fillPolygon(new int[] { lastSSX + 5, lastSSX + 5, lastSSX },
- new int[] { y + iconOffset, y + 14 + iconOffset,
- y + 8 + iconOffset }, 3);
+ new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+ 3);
x1 += 5;
}
if (diffdownstream)
// display a forward arrow
if (diffdownstream)
{
- g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 }, new int[] {
- y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
+ g.fillPolygon(new int[] { x2 - 5, x2 - 5, x2 },
+ new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset },
+ 3);
x2 -= 5;
}
if (diffupstream)
useClip = false;
}
+ rendererFactoryI = AnnotationRendererFactory.getRendererFactory();
updateFromAlignViewport(av);
}
* the alignment has no colourscheme set
* (would like to use user preference but n/a for applet)
*/
- ColourSchemeI col = av.getAlignment().isNucleotide() ? new NucleotideColourScheme()
+ ColourSchemeI col = av.getAlignment().isNucleotide()
+ ? new NucleotideColourScheme()
: new ZappoColourScheme();
profcolour = new ResidueShader(col);
}
// properties/rendering attributes as a global 'alignment group' which holds
// all vis settings for the alignment as a whole rather than a subset
//
- if (aa.autoCalculated
- && (aa.label.startsWith("Consensus") || aa.label
- .startsWith("cDNA Consensus")))
+ if (aa.autoCalculated && (aa.label.startsWith("Consensus")
+ || aa.label.startsWith("cDNA Consensus")))
{
boolean forComplement = aa.label.startsWith("cDNA Consensus");
if (aa.groupRef != null && aa.groupRef.consensusData != null
{
if (forComplement)
{
- return AAFrequency.extractCdnaProfile(
- complementConsensus[column], av_ignoreGapsConsensus);
+ return AAFrequency.extractCdnaProfile(complementConsensus[column],
+ av_ignoreGapsConsensus);
}
else
{
boolean rna = false;
+ private AnnotationRendererFactoryI rendererFactoryI;
+
/**
* Render the annotation rows associated with an alignment.
*
.getAlignmentStrucConsensusAnnotation();
final AlignmentAnnotation complementConsensusAnnot = av
.getComplementConsensusAnnotation();
- boolean renderHistogram = true, renderProfile = true, normaliseProfile = false, isRNA = rna;
+ boolean renderHistogram = true, renderProfile = true,
+ normaliseProfile = false, isRNA = rna;
BitSet graphGroupDrawn = new BitSet();
int charOffset = 0; // offset for a label
lastSS = ' ';
lastSSX = 0;
- if (!useClip
- || ((y - charHeight) < visHeight && (y + row.height + charHeight * 2) >= sOffset))
+ if (!useClip || ((y - charHeight) < visHeight
+ && (y + row.height + charHeight * 2) >= sOffset))
{// if_in_visible_region
if (!clipst)
{
{
y += charHeight;
usedFaded = true;
- g.drawImage(fadedImage, 0, y - row.height, imgWidth, y, 0, y
- - row.height, imgWidth, y, annotationPanel);
+ g.drawImage(fadedImage, 0, y - row.height, imgWidth, y, 0,
+ y - row.height, imgWidth, y, annotationPanel);
g.setColor(Color.black);
// g.drawString("Calculating "+aa[i].label+"....",20, y-row.height/2);
{
if (hasHiddenColumns)
{
- column = hiddenColumns.adjustForHiddenColumns(startRes + x);
+ column = hiddenColumns.visibleToAbsoluteColumn(startRes + x);
if (column > row_annotations.length - 1)
{
break;
{
validRes = true;
}
- final String displayChar = validRes ? row_annotations[column].displayCharacter
+ final String displayChar = validRes
+ ? row_annotations[column].displayCharacter
: null;
if (x > -1)
{
if (column == 0 || row.graph > 0)
{
- g.drawString(displayChar, (x * charWidth) + charOffset, y
- + iconOffset);
+ g.drawString(displayChar, (x * charWidth) + charOffset,
+ y + iconOffset);
}
- else if (row_annotations[column - 1] == null
- || (labelAllCols
- || !displayChar
- .equals(row_annotations[column - 1].displayCharacter) || (displayChar
- .length() < 2 && row_annotations[column].secondaryStructure == ' ')))
+ else if (row_annotations[column - 1] == null || (labelAllCols
+ || !displayChar.equals(
+ row_annotations[column - 1].displayCharacter)
+ || (displayChar.length() < 2
+ && row_annotations[column].secondaryStructure == ' ')))
{
- g.drawString(displayChar, x * charWidth + charOffset, y
- + iconOffset);
+ g.drawString(displayChar, x * charWidth + charOffset,
+ y + iconOffset);
}
g.setFont(ofont);
}
{
int nb_annot = x - temp;
- // System.out.println("\t type :"+lastSS+"\t x :"+x+"\t nbre annot :"+nb_annot);
+ // System.out.println("\t type :"+lastSS+"\t x :"+x+"\t nbre
+ // annot :"+nb_annot);
switch (lastSS)
{
case '(': // Stem case for RNA secondary structure
break;
default:
g.setColor(Color.gray);
- g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth)
- - lastSSX, 2);
+ g.fillRect(lastSSX, y + 6 + iconOffset,
+ (x * charWidth) - lastSSX, 2);
temp = x;
break;
}
row.graphMin, row.graphMax, y, renderHistogram,
renderProfile, normaliseProfile);
}
+ else
+ {
+ AnnotationRowRendererI renderer = rendererFactoryI
+ .getRendererFor(row);
+ if (renderer != null)
+ {
+ renderer.renderRow(g, charWidth, charHeight,
+ hasHiddenColumns, av, hiddenColumns, columnSelection,
+ row, row_annotations, startRes, endRes, row.graphMin,
+ row.graphMax, y);
+ }
+ if (debugRedraw)
+ {
+ if (renderer == null)
+ {
+ System.err.println("No renderer found for "
+ + row.toString());
+ }
+ else
+ {
+ System.err.println("rendered with "
+ + renderer.getClass().toString());
+ }
+ }
+
+ }
}
}
else
{
clipend = true;
}
- }// end if_in_visible_region
+ } // end if_in_visible_region
if (row.graph > 0 && row.hasText)
{
y += charHeight;
{
if (clipst)
{
- System.err.println("Start clip at : " + yfrom + " (index " + f_i
- + ")");
+ System.err.println(
+ "Start clip at : " + yfrom + " (index " + f_i + ")");
}
if (clipend)
{
- System.err.println("End clip at : " + yto + " (index " + f_to
- + ")");
+ System.err.println(
+ "End clip at : " + yto + " (index " + f_to + ")");
}
}
;
private Color sdNOTCANONICAL_COLOUR;
void drawGlyphLine(Graphics g, Annotation[] row, int lastSSX, int x,
- int y, int iconOffset, int startRes, int column,
- boolean validRes, boolean validEnd)
+ int y, int iconOffset, int startRes, int column, boolean validRes,
+ boolean validEnd)
{
g.setColor(GLYPHLINE_COLOR);
g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth) - lastSSX, 2);
void drawSheetAnnot(Graphics g, Annotation[] row,
- int lastSSX, int x, int y, int iconOffset, int startRes, int column,
- boolean validRes, boolean validEnd)
+ int lastSSX, int x, int y, int iconOffset, int startRes,
+ int column, boolean validRes, boolean validEnd)
{
g.setColor(SHEET_COLOUR);
if (!validEnd || !validRes || row == null || row[column] == null
|| row[column].secondaryStructure != 'E')
{
- g.fillRect(lastSSX, y + 4 + iconOffset,
- (x * charWidth) - lastSSX - 4, 7);
- g.fillPolygon(new int[] { (x * charWidth) - 4, (x * charWidth) - 4,
- (x * charWidth) }, new int[] { y + iconOffset,
- y + 14 + iconOffset, y + 7 + iconOffset }, 3);
+ g.fillRect(lastSSX, y + 4 + iconOffset, (x * charWidth) - lastSSX - 4,
+ 7);
+ g.fillPolygon(
+ new int[]
+ { (x * charWidth) - 4, (x * charWidth) - 4, (x * charWidth) },
+ new int[]
+ { y + iconOffset, y + 14 + iconOffset, y + 7 + iconOffset },
+ 3);
}
else
{
- g.fillRect(lastSSX, y + 4 + iconOffset,
- (x + 1) * charWidth - lastSSX, 7);
+ g.fillRect(lastSSX, y + 4 + iconOffset, (x + 1) * charWidth - lastSSX,
+ 7);
}
}
void drawHelixAnnot(Graphics g, Annotation[] row, int lastSSX, int x,
- int y, int iconOffset, int startRes, int column,
- boolean validRes, boolean validEnd)
+ int y, int iconOffset, int startRes, int column, boolean validRes,
+ boolean validEnd)
{
g.setColor(HELIX_COLOUR);
- int sCol = (lastSSX / charWidth) + startRes;
+ int sCol = (lastSSX / charWidth)
+ + hiddenColumns.visibleToAbsoluteColumn(startRes);
int x1 = lastSSX;
int x2 = (x * charWidth);
else
{
// g.setColor(Color.magenta);
- g.fillRoundRect(lastSSX + ofs, y + 4 + iconOffset, x2 - x1 - ofs
- + 1, 8, 0, 0);
+ g.fillRoundRect(lastSSX + ofs, y + 4 + iconOffset,
+ x2 - x1 - ofs + 1, 8, 0, 0);
}
}
void drawLineGraph(Graphics g, AlignmentAnnotation _aa,
- Annotation[] aa_annotations, int sRes, int eRes, int y,
- float min, float max, int graphHeight)
+ Annotation[] aa_annotations, int sRes, int eRes, int y, float min,
+ float max, int graphHeight)
{
if (sRes > aa_annotations.length)
{
column = sRes + x;
if (hasHiddenColumns)
{
- column = hiddenColumns.adjustForHiddenColumns(column);
+ column = hiddenColumns.visibleToAbsoluteColumn(column);
}
if (column > aaMax)
g.setColor(aa_annotations[column].colour);
}
- y1 = y
- - (int) (((aa_annotations[column - 1].value - min) / range) * graphHeight);
- y2 = y
- - (int) (((aa_annotations[column].value - min) / range) * graphHeight);
+ y1 = y - (int) (((aa_annotations[column - 1].value - min) / range)
+ * graphHeight);
+ y2 = y - (int) (((aa_annotations[column].value - min) / range)
+ * graphHeight);
- g.drawLine(x * charWidth - charWidth / 2, y1, x * charWidth
- + charWidth / 2, y2);
+ g.drawLine(x * charWidth - charWidth / 2, y1,
+ x * charWidth + charWidth / 2, y2);
x++;
}
g.setColor(_aa.threshold.colour);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
- BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f }, 0f));
+ BasicStroke.JOIN_ROUND, 3f, new float[]
+ { 5f, 3f }, 0f));
y2 = (int) (y - ((_aa.threshold.value - min) / range) * graphHeight);
g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
column = sRes + x;
if (hasHiddenColumns)
{
- column = hiddenColumns.adjustForHiddenColumns(column);
+ column = hiddenColumns.visibleToAbsoluteColumn(column);
}
if (column > aaMax)
g.setColor(aa_annotations[column].colour);
}
- y1 = y
- - (int) (((aa_annotations[column].value - min) / (range)) * _aa.graphHeight);
+ y1 = y - (int) (((aa_annotations[column].value - min) / (range))
+ * _aa.graphHeight);
if (renderHistogram)
{
ht += scl;
// next profl[] position is profile % for the character(s)
scl = htn * scale * profl[c++];
- lm = ofont.getLineMetrics(dc, 0, 1, g.getFontMetrics()
- .getFontRenderContext());
- Font font = ofont.deriveFont(AffineTransform.getScaleInstance(
- wdth, scl / lm.getAscent()));
+ lm = ofont.getLineMetrics(dc, 0, 1,
+ g.getFontMetrics().getFontRenderContext());
+ Font font = ofont.deriveFont(AffineTransform
+ .getScaleInstance(wdth, scl / lm.getAscent()));
g.setFont(font);
lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g);
}
g.setColor(colour == Color.white ? Color.lightGray : colour);
- hght = (ht + (scl - lm.getDescent() - lm.getBaselineOffsets()[lm
- .getBaselineIndex()]));
+ hght = (ht + (scl - lm.getDescent()
+ - lm.getBaselineOffsets()[lm.getBaselineIndex()]));
g.drawChars(dc, 0, dc.length, x * charWidth, (int) hght);
valuesProcessed++;
g.setColor(_aa.threshold.colour);
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
- BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f }, 0f));
+ BasicStroke.JOIN_ROUND, 3f, new float[]
+ { 5f, 3f }, 0f));
- y2 = (int) (y - ((_aa.threshold.value - min) / range)
- * _aa.graphHeight);
+ y2 = (int) (y
+ - ((_aa.threshold.value - min) / range) * _aa.graphHeight);
g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
g2.setStroke(new BasicStroke());
}
--- /dev/null
+ /**
+ *
+ */
+ package jalview.renderer;
+
+ import jalview.api.AlignViewportI;
+ import jalview.datamodel.AlignmentAnnotation;
+ import jalview.datamodel.Annotation;
+ import jalview.datamodel.ColumnSelection;
+ import jalview.datamodel.ContactListI;
+ import jalview.datamodel.ContactRange;
+ import jalview.datamodel.HiddenColumns;
+ import jalview.renderer.api.AnnotationRowRendererI;
+
+ import java.awt.Color;
+ import java.awt.Graphics;
+
+ /**
+ * @author jprocter
+ *
+ */
+ public class ContactMapRenderer implements AnnotationRowRendererI
+ {
+
+ @Override
+ public void renderRow(Graphics g, int charWidth, int charHeight,
+ boolean hasHiddenColumns, AlignViewportI viewport, HiddenColumns hiddenColumns,
+ ColumnSelection columnSelection, AlignmentAnnotation _aa,
+ Annotation[] aa_annotations, int sRes, int eRes, float min,
+ float max, int y)
+ {
+ if (sRes > aa_annotations.length)
+ {
+ return;
+ }
+ eRes = Math.min(eRes, aa_annotations.length);
+
+ int x = 0, y2 = y;
+
+ g.setColor(Color.pink);
+
+ g.drawLine(x, y2, (eRes - sRes) * charWidth, y2);
+
+ int column;
+ int aaMax = aa_annotations.length - 1;
+ while (x < eRes - sRes)
+ {
+ column = sRes + x;
+ if (hasHiddenColumns)
+ {
- column = hiddenColumns.adjustForHiddenColumns(column);
++ column = hiddenColumns.visibleToAbsoluteColumn(column);
+ }
+
+ if (column > aaMax)
+ {
+ break;
+ }
+
+ if (aa_annotations[column] == null)
+ {
+ x++;
+ continue;
+ }
+ /*
+ * {profile type, #values, total count, char1, pct1, char2, pct2...}
+ */
+ ContactListI contacts = viewport.getContactList(_aa, column);
+ if (contacts == null)
+ {
+ return;
+ }
+
+ // cell height to render
+ double scale = (_aa.graphHeight < contacts.getContactHeight()) ? 1
+ : ((double) _aa.graphHeight)
+ / (double) contacts.getContactHeight();
+ int cstart, cend = -1;
+ for (int ht = y2, eht = y2 - _aa.graphHeight; ht >= eht; ht -= scale)
+ {
+ cstart = cend + 1;
+ cend = Math.max(cstart + 1, contacts.getContactHeight()
+ * ((ht - y2) / _aa.graphHeight));
+ // TODO show maximum colour for range - sort of done
+ // also need a 'getMaxPosForRange(start,end)'
+ g.setColor(getColorForRange(min, max, contacts, cstart, cend));
+
+ if (scale > 1)
+ {
+ g.fillRect(x * charWidth, ht, charWidth, 1 + (int) scale);
+ }
+ else
+ {
+ g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht);
+ }
+ }
+ x++;
+ }
+
+ }
+
+ Color minColor = Color.white, maxColor = Color.magenta;
+
+
+ Color shadeFor(float min, float max, float value)
+ {
+ return jalview.util.ColorUtils.getGraduatedColour(value, 0, minColor,
+ max, maxColor);
+ }
+
+ public Color getColorForRange(float min, float max, ContactListI cl,
+ int i, int j)
+ {
+ ContactRange cr = cl.getRangeFor(i, j);
+ // average for moment - probably more interested in maxIntProj though
+ return shadeFor(min, max, (float) cr.getMean());
+ }
+
+ }
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.analysis.Conservation;
+import jalview.analysis.TreeModel;
import jalview.api.AlignCalcManagerI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.Annotation;
-import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
+ import jalview.datamodel.ContactListI;
import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
import jalview.datamodel.ProfilesI;
import java.util.Deque;
import java.util.HashMap;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
* @author jimp
*
*/
-public abstract class AlignmentViewport implements AlignViewportI,
- CommandListener, VamsasSource
+public abstract class AlignmentViewport
+ implements AlignViewportI, CommandListener, VamsasSource
{
- final protected ViewportRanges ranges;
+ protected ViewportRanges ranges;
protected ViewStyleI viewStyle = new ViewStyle();
public void setWrapAlignment(boolean state)
{
viewStyle.setWrapAlignment(state);
+ ranges.setWrappedMode(state);
}
/**
viewStyle.setSeqNameItalics(default1);
}
-
-
@Override
public AlignmentI getAlignment()
{
{
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);
}
* retain any colour thresholds per group while
* changing choice of colour scheme (JAL-2386)
*/
- sg.setColourScheme(cs);
+ sg.setColourScheme(
+ cs == null ? null : cs.getInstance(this, sg));
if (cs != null)
{
- sg.getGroupColourScheme()
- .alignmentChanged(sg, hiddenRepSequences);
+ sg.getGroupColourScheme().alignmentChanged(sg,
+ hiddenRepSequences);
}
}
}
@Override
public ColourSchemeI getGlobalColourScheme()
{
- return residueShading == null ? null : residueShading
- .getColourScheme();
+ return residueShading == null ? null : residueShading.getColourScheme();
}
@Override
{
return;
}
- if (calculator
- .getRegisteredWorkersOfClass(jalview.workers.ConservationThread.class) == null)
+ if (calculator.getRegisteredWorkersOfClass(
+ jalview.workers.ConservationThread.class) == null)
{
- calculator.registerWorker(new jalview.workers.ConservationThread(
- this, ap));
+ calculator.registerWorker(
+ new jalview.workers.ConservationThread(this, ap));
}
}
{
return;
}
- if (calculator.getRegisteredWorkersOfClass(ConsensusThread.class) == null)
+ if (calculator
+ .getRegisteredWorkersOfClass(ConsensusThread.class) == null)
{
calculator.registerWorker(new ConsensusThread(this, ap));
}
}
if (doConsensus)
{
- if (calculator
- .getRegisteredWorkersOfClass(ComplementConsensusThread.class) == null)
+ if (calculator.getRegisteredWorkersOfClass(
+ ComplementConsensusThread.class) == null)
{
calculator
.registerWorker(new ComplementConsensusThread(this, ap));
{
return;
}
- if (calculator.getRegisteredWorkersOfClass(StrucConsensusThread.class) == null)
+ if (calculator.getRegisteredWorkersOfClass(
+ StrucConsensusThread.class) == null)
{
calculator.registerWorker(new StrucConsensusThread(this, ap));
}
groupConsensus = null;
groupConservation = null;
hconsensus = null;
+ hconservation = null;
hcomplementConsensus = null;
- // colour scheme may hold reference to consensus
- residueShading = null;
- // TODO remove listeners from changeSupport?
+ gapcounts = null;
+ calculator = null;
+ residueShading = null; // may hold a reference to Consensus
changeSupport = null;
+ ranges = null;
+ currentTree = null;
+ selectionGroup = null;
setAlignment(null);
}
{
if (sequenceSetID != null)
{
- System.err
- .println("Warning - overwriting a sequenceSetId for a viewport!");
+ System.err.println(
+ "Warning - overwriting a sequenceSetId for a viewport!");
}
sequenceSetID = new String(newid);
}
public void removePropertyChangeListener(
java.beans.PropertyChangeListener listener)
{
- changeSupport.removePropertyChangeListener(listener);
+ if (changeSupport != null)
+ {
+ changeSupport.removePropertyChangeListener(listener);
+ }
}
/**
// 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);
+ List<SequenceI> tmp = alignment.getHiddenSequences()
+ .showAll(hiddenRepSequences);
for (SequenceI seq : tmp)
{
selectionGroup.addSequence(seq, false);
hiddenRepSequences = null;
+ ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
firePropertyChange("alignment", null, alignment.getSequences());
// used to set hasHiddenRows/hiddenRepSequences here, after the property
// changed event
public void showSequence(int index)
{
- List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(
- index, hiddenRepSequences);
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+
+ List<SequenceI> tmp = alignment.getHiddenSequences().showSequence(index,
+ hiddenRepSequences);
if (tmp.size() > 0)
{
if (selectionGroup == null)
selectionGroup.addSequence(seq, false);
setSequenceAnnotationsVisible(seq, true);
}
+
+ ranges.setStartEndSeq(startSeq, endSeq + tmp.size());
+
firePropertyChange("alignment", null, alignment.getSequences());
sendSelection();
}
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);
firePropertyChange("alignment", null, alignment.getSequences());
}
}
}
int gsize = selectionGroup.getSize();
- SequenceI[] hseqs = selectionGroup.getSequences().toArray(
- new SequenceI[gsize]);
+ SequenceI[] hseqs = selectionGroup.getSequences()
+ .toArray(new SequenceI[gsize]);
hideSequence(hseqs);
setSelectionGroup(null);
*/
public boolean isHiddenRepSequence(SequenceI seq)
{
- return (hiddenRepSequences != null && hiddenRepSequences
- .containsKey(seq));
+ return (hiddenRepSequences != null
+ && hiddenRepSequences.containsKey(seq));
}
/**
@Override
public int adjustForHiddenSeqs(int alignmentIndex)
{
- return alignment.getHiddenSequences().adjustForHiddenSeqs(
- alignmentIndex);
+ return alignment.getHiddenSequences()
+ .adjustForHiddenSeqs(alignmentIndex);
}
@Override
public void invertColumnSelection()
{
colSel.invertColumnSelection(0, alignment.getWidth(), alignment);
+ isColSelChanged(true);
}
@Override
}
@Override
- public CigarArray getViewAsCigars(boolean selectedRegionOnly)
- {
- return new CigarArray(alignment, alignment.getHiddenColumns(),
- (selectedRegionOnly ? selectionGroup : null));
- }
-
- @Override
public jalview.datamodel.AlignmentView getAlignmentView(
boolean selectedOnly)
{
boolean selectedOnly, boolean markGroups)
{
return new AlignmentView(alignment, alignment.getHiddenColumns(),
- selectionGroup, alignment.getHiddenColumns() != null
+ selectionGroup,
+ alignment.getHiddenColumns() != null
&& alignment.getHiddenColumns().hasHiddenColumns(),
- selectedOnly,
- markGroups);
+ selectedOnly, markGroups);
}
@Override
if (alignment.getHiddenColumns() != null
&& alignment.getHiddenColumns().hasHiddenColumns())
{
- selection = alignment.getHiddenColumns().getVisibleSequenceStrings(
- start, end, seqs);
+ for (i = 0; i < iSize; i++)
+ {
+ Iterator<int[]> blocks = alignment.getHiddenColumns()
+ .getVisContigsIterator(start, end + 1, false);
+ selection[i] = seqs[i].getSequenceStringFromIterator(blocks);
+ }
}
else
{
{
if (start == 0)
{
- start = hidden.adjustForHiddenColumns(start);
+ start = hidden.visibleToAbsoluteColumn(start);
}
- end = hidden.getHiddenBoundaryRight(start);
+ end = hidden.getNextHiddenBoundary(false, start);
if (start == end)
{
end = max;
if (hidden != null && hidden.hasHiddenColumns())
{
- start = hidden.adjustForHiddenColumns(end);
- start = hidden.getHiddenBoundaryLeft(start) + 1;
+ start = hidden.visibleToAbsoluteColumn(end);
+ start = hidden.getNextHiddenBoundary(true, start) + 1;
}
} while (end < max);
AlignmentAnnotation clone = new AlignmentAnnotation(annot);
if (selectedOnly && selectionGroup != null)
{
- alignment.getHiddenColumns().makeVisibleAnnotation(
- selectionGroup.getStartRes(),
- selectionGroup.getEndRes(), clone);
+ clone.makeVisibleAnnotation(
+ selectionGroup.getStartRes(), selectionGroup.getEndRes(),
+ alignment.getHiddenColumns());
}
else
{
- alignment.getHiddenColumns().makeVisibleAnnotation(clone);
+ clone.makeVisibleAnnotation(alignment.getHiddenColumns());
}
ala.add(clone);
}
{
gapcounts = new AlignmentAnnotation("Occupancy",
MessageManager.getString("label.occupancy_descr"),
- new Annotation[1], 0f,
- alignment.getHeight(), AlignmentAnnotation.BAR_GRAPH);
+ new Annotation[1], 0f, alignment.getHeight(),
+ AlignmentAnnotation.BAR_GRAPH);
gapcounts.hasText = true;
gapcounts.autoCalculated = true;
gapcounts.scaleColLabel = true;
{
conservation = new AlignmentAnnotation("Conservation",
MessageManager.formatMessage("label.conservation_descr",
- getConsPercGaps()), new Annotation[1],
- 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
+ getConsPercGaps()),
+ new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
conservation.hasText = true;
conservation.autoCalculated = true;
alignment.addAnnotation(conservation);
viewStyle = new ViewStyle(settingsForView);
if (residueShading != null)
{
- residueShading.setConservationApplied(settingsForView
- .isConservationColourSelected());
+ residueShading.setConservationApplied(
+ settingsForView.isConservationColourSelected());
}
}
return sortAnnotationsBy;
}
- public void setSortAnnotationsBy(SequenceAnnotationOrder sortAnnotationsBy)
+ public void setSortAnnotationsBy(
+ SequenceAnnotationOrder sortAnnotationsBy)
{
this.sortAnnotationsBy = sortAnnotationsBy;
}
return 0;
}
boolean iAmProtein = !getAlignment().isNucleotide();
- AlignmentI proteinAlignment = iAmProtein ? getAlignment() : complement
- .getAlignment();
+ AlignmentI proteinAlignment = iAmProtein ? getAlignment()
+ : complement.getAlignment();
if (proteinAlignment == null)
{
return 0;
*/
int lastSeq = alignment.getHeight() - 1;
List<AlignedCodonFrame> seqMappings = null;
- for (int seqNo = ranges.getStartSeq(); seqNo < lastSeq; seqNo++, seqOffset++)
+ for (int seqNo = ranges
+ .getStartSeq(); seqNo <= lastSeq; seqNo++, seqOffset++)
{
sequence = getAlignment().getSequenceAt(seqNo);
if (hiddenSequences != null && hiddenSequences.isHidden(sequence))
{
continue;
}
- seqMappings = MappingUtils
- .findMappingsForSequenceAndOthers(sequence, mappings,
- getCodingComplement().getAlignment().getSequences());
+ seqMappings = MappingUtils.findMappingsForSequenceAndOthers(sequence,
+ mappings,
+ getCodingComplement().getAlignment().getSequences());
if (!seqMappings.isEmpty())
{
break;
*/
private SearchResultsI searchResults = null;
+ protected TreeModel currentTree = null;
+
@Override
public boolean hasSearchResults()
{
return searchResults;
}
+ @Override
+ public ContactListI getContactList(AlignmentAnnotation _aa, int column)
+ {
+ return alignment.getContactListFor(_aa, column);
+ }
+
/**
* get the consensus sequence as displayed under the PID consensus annotation
* row.
}
}
}
-
+
SequenceI sq = new Sequence("Consensus", seqs.toString());
sq.setDescription("Percentage Identity Consensus "
+ ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
return sq;
}
+
+ @Override
+ public void setCurrentTree(TreeModel tree)
+ {
+ currentTree = tree;
+ }
+
+ @Override
+ public TreeModel getCurrentTree()
+ {
+ return currentTree;
+ }
+
+ /**
+ * flag set to indicate if structure views might be out of sync with sequences
+ * in the alignment
+ */
+
+ private boolean needToUpdateStructureViews = false;
+
+ @Override
+ public boolean isUpdateStructures()
+ {
+ return needToUpdateStructureViews;
+ }
+
+ @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)
+ {
+ col = col.brighter();
+
+ for (SequenceI sq : sequenceGroup.getSequences())
+ {
+ setSequenceColour(sq, col);
+ }
+ }
+
+ if (codingComplement != null)
+ {
+ SequenceGroup mappedGroup = MappingUtils
+ .mapSequenceGroup(sequenceGroup, this, codingComplement);
+ if (mappedGroup.getSequences().size() > 0)
+ {
+ codingComplement.getAlignment().addGroup(mappedGroup);
+
+ if (col != null)
+ {
+ for (SequenceI seq : mappedGroup.getSequences())
+ {
+ codingComplement.setSequenceColour(seq, col);
+ }
+ }
+ }
+ // propagate the structure view update flag according to our own setting
+ codingComplement.setUpdateStructures(needToUpdateStructureViews);
+ }
+ }
}