* get sequence residues overlapping column region
* and features for residue positions and specified types
*/
- // TODO new method findPositions(startCol, endCol)? JAL-2544
- int startResidue = seqs[i].findPosition(startCol);
- int endResidue = seqs[i].findPosition(endCol);
String[] types = featureTypes == null ? null : featureTypes
.toArray(new String[featureTypes.size()]);
- List<SequenceFeature> sfs = seqs[i].findFeatures(startResidue,
- endResidue, types);
+ List<SequenceFeature> sfs = seqs[i].findFeatures(startCol + 1,
+ endCol + 1, types);
seqScores[i] = 0;
scores[i] = 0.0;
SequenceFeature sf = it.next();
/*
- * double-check feature overlaps columns (JAL-2544)
- * (could avoid this with a findPositions(fromCol, toCol) method)
- * findIndex returns base 1 column values, startCol/endCol are base 0
- */
- if (seqs[i].findIndex(sf.getBegin()) > endCol + 1
- || seqs[i].findIndex(sf.getEnd()) < startCol + 1)
- {
- it.remove();
- continue;
- }
-
- /*
* accept all features with null or empty group, otherwise
* check group is one of the currently visible groups
*/
/**
* Builds and returns a map containing a (possibly empty) list (one per
* SeqCigar) of visible feature types at the given column position. The map
- * has no entry for sequences which are gapped at the column position.
+ * does not include entries for features which straddle a gapped column
+ * positions.
*
* @param seqs
* @param columnPosition
+ * (0..)
* @return
*/
protected Map<SeqCigar, Set<String>> findFeatureTypesAtColumn(
int spos = seq.findPosition(columnPosition);
if (spos != -1)
{
+ /*
+ * position is not a gap
+ */
Set<String> types = new HashSet<String>();
- List<SequenceFeature> sfs = fr.findFeaturesAtRes(seq.getRefSeq(),
- spos);
+ List<SequenceFeature> sfs = fr.findFeaturesAtResidue(
+ seq.getRefSeq(), spos);
for (SequenceFeature sf : sfs)
{
types.add(sf.getType());
*
* @param sequence
* @param column
+ * aligned column position (1..)
* @param g
* @return
*/
void setGroupVisibility(String group, boolean visible);
/**
- * Returns features at the specified position on the given sequence.
+ * Returns features at the specified aligned column on the given sequence.
+ * Non-positional features are not included. If the column has a gap, then
+ * enclosing features are included (but not contact features).
+ *
+ * @param sequence
+ * @param column
+ * aligned column position (1..)
+ * @return
+ */
+ List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column);
+
+ /**
+ * Returns features at the specified residue position on the given sequence.
* Non-positional features are not included.
*
* @param sequence
- * @param res
+ * @param resNo
+ * residue position (start..)
* @return
*/
- List<SequenceFeature> findFeaturesAtRes(SequenceI sequence, int res);
+ List<SequenceFeature> findFeaturesAtResidue(SequenceI sequence, int resNo);
/**
* get current displayed types, in ordering of rendering (on top last)
* @return
*/
float getTransparency();
+
}
import java.awt.event.MouseMotionListener;
import java.util.Collections;
import java.util.List;
-import java.util.ListIterator;
import java.util.Vector;
public class SeqPanel extends Panel implements MouseMotionListener,
}
int seq = findSeq(evt);
- int res = findRes(evt);
+ int res = findColumn(evt);
if (seq < 0 || res < 0)
{
av.setSelectionGroup(null);
}
- int column = findRes(evt);
- boolean isGapped = Comparison.isGap(sequence.getCharAt(column));
- List<SequenceFeature> features = findFeaturesAtRes(sequence,
- sequence.findPosition(column));
- if (isGapped)
- {
- removeAdjacentFeatures(features, column + 1, sequence);
- }
+ int column = findColumn(evt);
+ List<SequenceFeature> features = findFeaturesAtColumn(sequence,
+ column + 1);
if (!features.isEmpty())
{
int wrappedBlock = -1;
- int findRes(MouseEvent evt)
+ /**
+ * Returns the aligned sequence position (base 0) at the mouse position, or
+ * the closest visible one
+ *
+ * @param evt
+ * @return
+ */
+ int findColumn(MouseEvent evt)
{
int res = 0;
int x = evt.getX();
{
int seq = findSeq(evt);
- int res = findRes(evt);
+ int res = findColumn(evt);
if (seq < av.getAlignment().getHeight()
&& res < av.getAlignment().getSequenceAt(seq).getLength())
@Override
public void mouseMoved(MouseEvent evt)
{
- final int column = findRes(evt);
+ final int column = findColumn(evt);
int seq = findSeq(evt);
if (seq >= av.getAlignment().getHeight() || seq < 0 || column < 0)
*/
if (av.isShowSequenceFeatures())
{
- List<SequenceFeature> allFeatures = findFeaturesAtRes(sequence,
- respos);
- if (isGapped)
- {
- removeAdjacentFeatures(allFeatures, column + 1, sequence);
- }
+ List<SequenceFeature> allFeatures = findFeaturesAtColumn(sequence,
+ column + 1);
for (SequenceFeature sf : allFeatures)
{
tooltipText.append(sf.getType() + " " + sf.begin + ":" + sf.end);
}
}
- List<SequenceFeature> findFeaturesAtRes(SequenceI sequence, int res)
- {
- return seqCanvas.getFeatureRenderer().findFeaturesAtRes(sequence, res);
- }
-
/**
- * Removes from the list of features any that start after, or end before, the
- * given column position. This allows us to retain only those features
- * adjacent to a gapped position that straddle the position. Contact features
- * that 'straddle' the position are also removed, since they are not 'at' the
- * position.
+ * Returns features at the specified aligned column on the given sequence.
+ * Non-positional features are not included. If the column has a gap, then
+ * enclosing features are included (but not contact features).
*
- * @param features
- * @param column
- * alignment column (1..)
* @param sequence
+ * @param column
+ * (1..)
+ * @return
*/
- protected void removeAdjacentFeatures(List<SequenceFeature> features,
- int column, SequenceI sequence)
+ List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column)
{
- // TODO should this be an AlignViewController method (shared by gui)?
- ListIterator<SequenceFeature> it = features.listIterator();
- while (it.hasNext())
- {
- SequenceFeature sf = it.next();
- if (sf.isContactFeature()
- || sequence.findIndex(sf.getBegin()) > column
- || sequence.findIndex(sf.getEnd()) < column)
- {
- it.remove();
- }
- }
+ return seqCanvas.getFeatureRenderer().findFeaturesAtColumn(sequence, column);
}
Tooltip tooltip;
return;
}
- int res = findRes(evt);
+ int res = findColumn(evt);
if (res < 0)
{
scrollThread = null;
}
- int res = findRes(evt);
+ int column = findColumn(evt);
int seq = findSeq(evt);
oldSeq = seq;
startWrapBlock = wrappedBlock;
SequenceI sequence = av.getAlignment().getSequenceAt(seq);
- if (sequence == null || res > sequence.getLength())
+ if (sequence == null || column > sequence.getLength())
{
return;
}
stretchGroup = av.getSelectionGroup();
- if (stretchGroup == null || !stretchGroup.contains(sequence, res))
+ if (stretchGroup == null || !stretchGroup.contains(sequence, column))
{
- stretchGroup = av.getAlignment().findGroup(sequence, res);
+ stretchGroup = av.getAlignment().findGroup(sequence, column);
if (stretchGroup != null)
{
// only update the current selection if the popup menu has a group to
// DETECT RIGHT MOUSE BUTTON IN AWT
if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
{
- List<SequenceFeature> allFeatures = findFeaturesAtRes(sequence,
- sequence.findPosition(res));
+ List<SequenceFeature> allFeatures = findFeaturesAtColumn(sequence,
+ sequence.findPosition(column + 1));
Vector<String> links = null;
for (SequenceFeature sf : allFeatures)
if (av.cursorMode)
{
- seqCanvas.cursorX = findRes(evt);
+ seqCanvas.cursorX = findColumn(evt);
seqCanvas.cursorY = findSeq(evt);
seqCanvas.repaint();
return;
{
// define a new group here
SequenceGroup sg = new SequenceGroup();
- sg.setStartRes(res);
- sg.setEndRes(res);
+ sg.setStartRes(column);
+ sg.setEndRes(column);
sg.addSequence(sequence, false);
av.setSelectionGroup(sg);
stretchGroup = sg;
public void doMouseDraggedDefineMode(MouseEvent evt)
{
- int res = findRes(evt);
+ int res = findColumn(evt);
int y = findSeq(evt);
if (wrappedBlock != startWrapBlock)
static int findColumnsWithFeature(String featureType,
SequenceCollectionI sqcol, BitSet bs)
{
- final int startPosition = sqcol.getStartRes() + 1; // converted to base 1
- final int endPosition = sqcol.getEndRes() + 1;
+ final int startColumn = sqcol.getStartRes() + 1; // converted to base 1
+ final int endColumn = sqcol.getEndRes() + 1;
List<SequenceI> seqs = sqcol.getSequences();
int nseq = 0;
for (SequenceI sq : seqs)
{
if (sq != null)
{
- int ist = sq.findPosition(sqcol.getStartRes());
- int iend = sq.findPosition(sqcol.getEndRes()); // see JAL-2526
- List<SequenceFeature> sfs = sq.findFeatures(ist, iend, featureType);
- boolean overlap = false;
- for (SequenceFeature sf : sfs)
+ // int ist = sq.findPosition(sqcol.getStartRes());
+ List<SequenceFeature> sfs = sq.findFeatures(startColumn,
+ endColumn, featureType);
+
+ if (!sfs.isEmpty())
{
- // future functionality - featureType == null means mark columns
- // containing all displayed features
- if (sf != null && (featureType.equals(sf.getType())))
- {
- int sfStartCol = sq.findIndex(sf.getBegin());
- int sfEndCol = sq.findIndex(sf.getEnd()); // inefficient - JAL-2526
+ nseq++;
+ }
- if (sf.isContactFeature())
- {
- /*
- * 'contact' feature - check for 'start' or 'end'
- * position within the selected region
- */
- if (sfStartCol >= startPosition && sfStartCol <= endPosition)
- {
- bs.set(sfStartCol - 1);
- overlap = true;
- }
- if (sfEndCol >= startPosition && sfEndCol <= endPosition)
- {
- bs.set(sfEndCol - 1);
- overlap = true;
- }
- continue;
- }
+ for (SequenceFeature sf : sfs)
+ {
+ int sfStartCol = sq.findIndex(sf.getBegin());
+ int sfEndCol = sq.findIndex(sf.getEnd());
+ if (sf.isContactFeature())
+ {
/*
- * contiguous feature - select feature positions (if any)
- * within the selected region
+ * 'contact' feature - check for 'start' or 'end'
+ * position within the selected region
*/
- if (sfStartCol < startPosition)
- {
- sfStartCol = startPosition;
- }
- if (sfStartCol < ist)
+ if (sfStartCol >= startColumn && sfStartCol <= endColumn)
{
- sfStartCol = ist;
+ bs.set(sfStartCol - 1);
}
- if (sfEndCol > endPosition)
+ if (sfEndCol >= startColumn && sfEndCol <= endColumn)
{
- sfEndCol = endPosition;
- }
- for (; sfStartCol <= sfEndCol; sfStartCol++)
- {
- bs.set(sfStartCol - 1); // convert to base 0
- overlap = true;
+ bs.set(sfEndCol - 1);
}
+ continue;
+ }
+
+ /*
+ * contiguous feature - select feature positions (if any)
+ * within the selected region
+ */
+ if (sfStartCol < startColumn)
+ {
+ sfStartCol = startColumn;
+ }
+ // not sure what the point of this is
+ // if (sfStartCol < ist)
+ // {
+ // sfStartCol = ist;
+ // }
+ if (sfEndCol > endColumn)
+ {
+ sfEndCol = endColumn;
+ }
+ for (; sfStartCol <= sfEndCol; sfStartCol++)
+ {
+ bs.set(sfStartCol - 1); // convert to base 0
}
- }
- if (overlap)
- {
- nseq++;
}
}
}
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
+import java.util.ListIterator;
import java.util.Vector;
import com.stevesoft.pat.Regex;
}
/**
- * {@inheritDoc}
- */
- @Override
- public Range findPositions(int fromCol, int toCol)
- {
- /*
- * count residues before fromCol
- */
- int j = 0;
- int count = 0;
- int seqlen = sequence.length;
- while (j < fromCol && j < seqlen)
- {
- if (!Comparison.isGap(sequence[j]))
- {
- count++;
- }
- j++;
- }
-
- /*
- * find first and last residues between fromCol and toCol
- */
- int firstPos = 0;
- int lastPos = 0;
- int firstPosCol = 0;
- boolean foundFirst = false;
-
- while (j <= toCol && j < seqlen)
- {
- if (!Comparison.isGap(sequence[j]))
- {
- count++;
- if (!foundFirst)
- {
- firstPos = count;
- firstPosCol = j;
- foundFirst = true;
- }
- lastPos = count;
- }
- j++;
- }
-
- if (firstPos == 0)
- {
- /*
- * no residues in this range
- */
- return null;
- }
-
- /*
- * adjust for sequence start coordinate
- */
- firstPos += start - 1;
- lastPos += start - 1;
-
- return new Range(firstPos, lastPos);
- }
-
- /**
* Returns an int array where indices correspond to each residue in the
* sequence and the element value gives its position in the alignment
*
* {@inheritDoc}
*/
@Override
- public List<SequenceFeature> findFeatures(int from, int to,
+ public List<SequenceFeature> findFeatures(int fromColumn, int toColumn,
String... types)
{
+ int startPos = findPosition(fromColumn - 1); // convert base 1 to base 0
+ int endPos = findPosition(toColumn - 1);
+
+ List<SequenceFeature> result = new ArrayList<>();
if (datasetSequence != null)
{
- return datasetSequence.findFeatures(from, to, types);
+ result = datasetSequence.getFeatures().findFeatures(startPos, endPos,
+ types);
}
- return sequenceFeatureStore.findFeatures(from, to, types);
+ else
+ {
+ result = sequenceFeatureStore.findFeatures(startPos, endPos, types);
+ }
+
+ /*
+ * if the start or end column is gapped, startPos or endPos may be to the
+ * left or right, and we may have included adjacent or enclosing features;
+ * remove any that are not enclosing, non-contact features
+ */
+ if (endPos > this.end || Comparison.isGap(sequence[fromColumn - 1])
+ || Comparison.isGap(sequence[toColumn - 1]))
+ {
+ ListIterator<SequenceFeature> it = result.listIterator();
+ while (it.hasNext())
+ {
+ SequenceFeature sf = it.next();
+ int featureStartColumn = findIndex(sf.getBegin());
+ int featureEndColumn = findIndex(sf.getEnd());
+ boolean noOverlap = featureStartColumn > toColumn
+ || featureEndColumn < fromColumn;
+
+ /*
+ * reject an 'enclosing' feature if it is actually a contact feature
+ */
+ if (sf.isContactFeature() && featureStartColumn < fromColumn
+ && featureEndColumn > toColumn)
+ {
+ noOverlap = true;
+ }
+ if (noOverlap)
+ {
+ it.remove();
+ }
+ }
+ }
+
+ return result;
}
}
public int findPosition(int i);
/**
- * Returns the range of sequence positions included in the given alignment
- * position range. If no positions are included (the range is entirely gaps),
- * then returns null.
- *
- * <pre>
- * Example:
- * >Seq/8-13
- * ABC--DE-F
- * findPositions(1, 4) returns Range(9, 9) // B only
- * findPositions(3, 4) returns null // all gaps
- * findPositions(2, 6) returns Range(10, 12) // CDE
- * findPositions(3, 7) returns Range(11,12) // DE
- * </pre>
- *
- * @param fromCol
- * first aligned column position (base 0, inclusive)
- * @param toCol
- * last aligned column position (base 0, inclusive)
- *
- * @return
- */
- public Range findPositions(int fromCol, int toCol);
-
- /**
* Returns an int array where indices correspond to each residue in the
* sequence and the element value gives its position in the alignment
*
public List<DBRefEntry> getPrimaryDBRefs();
/**
- * Returns a (possibly empty) list of sequence features that overlap the range
- * from-to (inclusive), optionally restricted to one or more specified feature
- * types
+ * Returns a (possibly empty) list of sequence features that overlap the given
+ * alignment column range, optionally restricted to one or more specified
+ * feature types. If the range is all gaps, then features which enclose it are
+ * included (but not contact features).
*
- * @param from
- * @param to
+ * @param fromCol
+ * start column of range inclusive (1..)
+ * @param toCol
+ * end column of range inclusive (1..)
* @param types
+ * optional feature types to restrict results to
* @return
*/
- List<SequenceFeature> findFeatures(int from, int to, String... types);
+ List<SequenceFeature> findFeatures(int fromCol, int toCol, String... types);
}
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
+import jalview.io.HTMLOutput;
import jalview.jbgui.GAlignmentPanel;
import jalview.math.AlignmentDimension;
import jalview.schemes.ResidueProperties;
{
try
{
- int s, sSize = av.getAlignment().getHeight(), res, alwidth = av
- .getAlignment().getWidth(), g, gSize, f, fSize, sy;
+ int sSize = av.getAlignment().getHeight();
+ int alwidth = av.getAlignment().getWidth();
PrintWriter out = new PrintWriter(new FileWriter(imgMapFile));
- out.println(jalview.io.HTMLOutput.getImageMapHTML());
+ out.println(HTMLOutput.getImageMapHTML());
out.println("<img src=\"" + imageName
+ "\" border=\"0\" usemap=\"#Map\" >"
+ "<map name=\"Map\">");
- for (s = 0; s < sSize; s++)
+ for (int s = 0; s < sSize; s++)
{
- sy = s * av.getCharHeight() + scaleHeight;
+ int sy = s * av.getCharHeight() + scaleHeight;
SequenceI seq = av.getAlignment().getSequenceAt(s);
SequenceGroup[] groups = av.getAlignment().findAllGroups(seq);
- for (res = 0; res < alwidth; res++)
+ for (int column = 0; column < alwidth; column++)
{
StringBuilder text = new StringBuilder(512);
String triplet = null;
if (av.getAlignment().isNucleotide())
{
triplet = ResidueProperties.nucleotideName.get(seq
- .getCharAt(res) + "");
+ .getCharAt(column) + "");
}
else
{
- triplet = ResidueProperties.aa2Triplet.get(seq.getCharAt(res)
+ triplet = ResidueProperties.aa2Triplet.get(seq.getCharAt(column)
+ "");
}
continue;
}
- int seqPos = seq.findPosition(res);
- gSize = groups.length;
- for (g = 0; g < gSize; g++)
+ int seqPos = seq.findPosition(column);
+ int gSize = groups.length;
+ for (int g = 0; g < gSize; g++)
{
if (text.length() < 1)
{
text.append("<area shape=\"rect\" coords=\"")
- .append((idWidth + res * av.getCharWidth()))
+ .append((idWidth + column * av.getCharWidth()))
.append(",").append(sy).append(",")
- .append((idWidth + (res + 1) * av.getCharWidth()))
+ .append((idWidth + (column + 1) * av.getCharWidth()))
.append(",").append((av.getCharHeight() + sy))
.append("\"").append(" onMouseOver=\"toolTip('")
.append(seqPos).append(" ").append(triplet);
}
- if (groups[g].getStartRes() < res
- && groups[g].getEndRes() > res)
+ if (groups[g].getStartRes() < column
+ && groups[g].getEndRes() > column)
{
text.append("<br><em>").append(groups[g].getName())
.append("</em>");
if (text.length() < 1)
{
text.append("<area shape=\"rect\" coords=\"")
- .append((idWidth + res * av.getCharWidth()))
+ .append((idWidth + column * av.getCharWidth()))
.append(",").append(sy).append(",")
- .append((idWidth + (res + 1) * av.getCharWidth()))
+ .append((idWidth + (column + 1) * av.getCharWidth()))
.append(",").append((av.getCharHeight() + sy))
.append("\"").append(" onMouseOver=\"toolTip('")
.append(seqPos).append(" ").append(triplet);
}
- if (!Comparison.isGap(seq.getCharAt(res)))
+ if (!Comparison.isGap(seq.getCharAt(column)))
{
- List<SequenceFeature> features = seq.findFeatures(seqPos,
- seqPos);
+ List<SequenceFeature> features = seq.findFeatures(column, column);
for (SequenceFeature sf : features)
{
if (sf.isContactFeature())
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.ListIterator;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
int seq = findSeq(evt);
if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
{
+ lastMouseSeq = -1;
return;
}
if (column == lastMouseColumn && seq == lastMouseSeq)
if (av.isShowSequenceFeatures())
{
List<SequenceFeature> features = ap.getFeatureRenderer()
- .findFeaturesAtRes(sequence.getDatasetSequence(), pos);
- if (isGapped)
- {
- removeAdjacentFeatures(features, column + 1, sequence);
- }
+ .findFeaturesAtColumn(sequence, column + 1);
seqARep.appendFeatures(tooltipText, pos, features,
this.ap.getSeqPanel().seqCanvas.fr.getMinMax());
}
}
}
- /**
- * Removes from the list of features any that start after, or end before, the
- * given column position. This allows us to retain only those features
- * adjacent to a gapped position that straddle the position. Contact features
- * that 'straddle' the position are also removed, since they are not 'at' the
- * position.
- *
- * @param features
- * @param column
- * alignment column (1..)
- * @param sequence
- */
- protected void removeAdjacentFeatures(List<SequenceFeature> features,
- final int column, SequenceI sequence)
- {
- // TODO should this be an AlignViewController method (and reused by applet)?
- ListIterator<SequenceFeature> it = features.listIterator();
- while (it.hasNext())
- {
- SequenceFeature sf = it.next();
- if (sf.isContactFeature()
- || sequence.findIndex(sf.getBegin()) > column
- || sequence.findIndex(sf.getEnd()) < column)
- {
- it.remove();
- }
- }
- }
-
private Point lastp = null;
/*
}
int column = findColumn(evt);
- boolean isGapped = Comparison.isGap(sequence.getCharAt(column));
/*
* find features at the position (if not gapped), or straddling
* the position (if at a gap)
*/
List<SequenceFeature> features = seqCanvas.getFeatureRenderer()
- .findFeaturesAtRes(sequence.getDatasetSequence(),
- sequence.findPosition(column));
- if (isGapped)
- {
- removeAdjacentFeatures(features, column, sequence);
- }
+ .findFeaturesAtColumn(sequence, column + 1);
if (!features.isEmpty())
{
*/
void showPopupMenu(MouseEvent evt)
{
- final int res = findColumn(evt);
+ final int column = findColumn(evt);
final int seq = findSeq(evt);
SequenceI sequence = av.getAlignment().getSequenceAt(seq);
List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
- .findFeaturesAtRes(sequence.getDatasetSequence(),
- sequence.findPosition(res));
+ .findFeaturesAtColumn(sequence, column + 1);
List<String> links = new ArrayList<>();
for (SequenceFeature sf : allFeatures)
{
* @param defaultColour
* @param seq
* @param column
- * alignment column position (base zero)
+ * alignment column position (0..)
* @return
*/
public Color findFeatureColour(Color defaultColour, SequenceI seq,
}
}
- Color c = featureRenderer.findFeatureColour(seq, column, g);
+ Color c = featureRenderer.findFeatureColour(seq, column + 1, g);
if (c == null)
{
return defaultColour;
package jalview.renderer.seqfeatures;
import jalview.api.AlignViewportI;
-import jalview.datamodel.Range;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.util.Comparison;
/*
* simple case - just find the topmost rendered visible feature colour
*/
- renderedColour = findFeatureColour(seq, seq.findPosition(column));
+ renderedColour = findFeatureColour(seq, column);
}
else
{
transparency));
}
- /*
- * get range of sequence positions within column range
- */
- Range seqRange = seq.findPositions(start, end);
- if (seqRange == null)
- {
- return null;
- }
-
Color drawnColour = null;
/*
continue;
}
- List<SequenceFeature> overlaps = seq.findFeatures(seqRange.start,
- seqRange.end, type);
+ List<SequenceFeature> overlaps = seq.findFeatures(start + 1, end + 1,
+ type);
for (SequenceFeature sf : overlaps)
{
/*
.findIndex(sf.end);
if (isContactFeature)
{
- boolean drawn = renderFeature(g, seq,
- featureStartCol - 1,
- featureStartCol - 1, featureColour,
- start, end, y1, colourOnly);
- drawn |= renderFeature(g, seq,
- featureEndCol - 1,
- featureEndCol - 1, featureColour,
- start, end, y1, colourOnly);
+ boolean drawn = renderFeature(g, seq, featureStartCol - 1,
+ featureStartCol - 1, featureColour, start, end, y1,
+ colourOnly);
+ drawn |= renderFeature(g, seq, featureEndCol - 1,
+ featureEndCol - 1, featureColour, start, end, y1,
+ colourOnly);
if (drawn)
{
drawnColour = featureColour;
}
/**
- * Returns the sequence feature colour rendered at the given sequence
- * position, or null if none found. The feature of highest render order (i.e.
- * on top) is found, subject to both feature type and feature group being
- * visible, and its colour returned.
+ * Returns the sequence feature colour rendered at the given column position,
+ * or null if none found. The feature of highest render order (i.e. on top) is
+ * found, subject to both feature type and feature group being visible, and
+ * its colour returned.
+ * <p>
+ * Note this method does not check for a gap in the column so would return the
+ * colour for features enclosing a gapped column. Check for gap before calling
+ * if different behaviour is wanted.
*
* @param seq
- * @param pos
+ * @param column
+ * (1..)
* @return
*/
- Color findFeatureColour(SequenceI seq, int pos)
+ Color findFeatureColour(SequenceI seq, int column)
{
/*
* check for new feature added while processing
continue;
}
- List<SequenceFeature> overlaps = seq.findFeatures(pos, pos, type);
+ List<SequenceFeature> overlaps = seq.findFeatures(column, column,
+ type);
for (SequenceFeature sequenceFeature : overlaps)
{
if (!featureGroupNotShown(sequenceFeature))
}
@Override
- public List<SequenceFeature> findFeaturesAtRes(SequenceI sequence, int res)
+ public List<SequenceFeature> findFeaturesAtColumn(SequenceI sequence, int column)
{
+ /*
+ * include features at the position provided their feature type is
+ * displayed, and feature group is null or marked for display
+ */
List<SequenceFeature> result = new ArrayList<SequenceFeature>();
- if (!av.areFeaturesDisplayed())
+ if (!av.areFeaturesDisplayed() || getFeaturesDisplayed() == null)
{
return result;
}
.getVisibleFeatures();
String[] visibleTypes = visibleFeatures
.toArray(new String[visibleFeatures.size()]);
-
- /*
- * include features at the position provided their feature type is
- * displayed, and feature group is null or marked for display
- */
- List<SequenceFeature> features = sequence.findFeatures(res, res,
+ List<SequenceFeature> features = sequence.findFeatures(column, column,
visibleTypes);
for (SequenceFeature sf : features)
.booleanValue();
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<SequenceFeature> findFeaturesAtResidue(SequenceI sequence,
+ int resNo)
+ {
+ List<SequenceFeature> result = new ArrayList<SequenceFeature>();
+ if (!av.areFeaturesDisplayed() || getFeaturesDisplayed() == null)
+ {
+ return result;
+ }
+
+ /*
+ * include features at the position provided their feature type is
+ * displayed, and feature group is null or the empty string
+ * or marked for display
+ */
+ Set<String> visibleFeatures = getFeaturesDisplayed()
+ .getVisibleFeatures();
+ String[] visibleTypes = visibleFeatures
+ .toArray(new String[visibleFeatures.size()]);
+ List<SequenceFeature> features = sequence.getFeatures().findFeatures(
+ resNo, resNo, visibleTypes);
+
+ for (SequenceFeature sf : features)
+ {
+ if (!featureGroupNotShown(sf))
+ {
+ result.add(sf);
+ }
+ }
+ return result;
+ }
+
}
*
* @param alignment
* @param col
+ * (0..)
* @param row
* @param fr
*/
{
return null;
}
- int pos = seq.findPosition(col);
/*
* compute a count for any displayed features at residue
*/
- // NB have to adjust pos if using AlignmentView.getVisibleAlignment
// see JAL-2075
- List<SequenceFeature> features = fr.findFeaturesAtRes(seq, pos);
+ List<SequenceFeature> features = fr.findFeaturesAtColumn(seq, col + 1);
int[] count = this.counter.count(String.valueOf(res), features);
return count;
}
Assert.assertEquals(af.getFeatureRenderer().getDisplayedFeatureTypes()
.size(), 1, "Should be just one feature type displayed");
// step through and check for pointwise feature presence/absence
- Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 1)
+ Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 1)
.size(), 0);
// step through and check for pointwise feature presence/absence
- Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 2)
+ Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 2)
.size(), 1);
// step through and check for pointwise feature presence/absence
- Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 3)
+ Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 3)
.size(), 0);
// step through and check for pointwise feature presence/absence
- Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 4)
+ Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 4)
.size(), 0);
// step through and check for pointwise feature presence/absence
- Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 5)
+ Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 5)
.size(), 1);
// step through and check for pointwise feature presence/absence
- Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtRes(aseq, 6)
+ Assert.assertEquals(af.getFeatureRenderer().findFeaturesAtColumn(aseq, 6)
.size(), 0);
}
seq.setDatasetSequence(seq2);
}
- @Test
- public void testFindPositions()
+ @Test(groups = { "Functional" })
+ public void testFindFeatures()
{
- SequenceI sq = new Sequence("Seq", "ABC--DE-F", 8, 13);
-
- Range range = sq.findPositions(1, 4); // BC
- assertEquals(new Range(9, 10), range);
-
- range = sq.findPositions(2, 4); // C
- assertEquals(new Range(10, 10), range);
-
- assertNull(sq.findPositions(3, 4)); // all gaps
+ SequenceI sq = new Sequence("test/8-16", "-ABC--DEF--GHI--");
+ sq.createDatasetSequence();
- range = sq.findPositions(2, 6); // CDE
- assertEquals(new Range(10, 12), range);
+ assertTrue(sq.findFeatures(1, 99).isEmpty());
- range = sq.findPositions(3, 7); // DE
- assertEquals(new Range(11, 12), range);
+ // add non-positional feature
+ SequenceFeature sf0 = new SequenceFeature("Cath", "desc", 0, 0, 2f,
+ null);
+ sq.addSequenceFeature(sf0);
+ // add feature on BCD
+ SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 9, 11, 2f,
+ null);
+ sq.addSequenceFeature(sf1);
+ // add feature on DE
+ SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 11, 12, 2f,
+ null);
+ sq.addSequenceFeature(sf2);
+ // add contact feature at [B, H]
+ SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc", 9,
+ 15, 2f,
+ null);
+ sq.addSequenceFeature(sf3);
+ // add contact feature at [F, G]
+ SequenceFeature sf4 = new SequenceFeature("Disulfide Bond", "desc", 13,
+ 14, 2f,
+ null);
+ sq.addSequenceFeature(sf4);
+
+ // no features in columns 1-2 (-A)
+ List<SequenceFeature> found = sq.findFeatures(1, 2);
+ assertTrue(found.isEmpty());
+
+ // columns 1-6 (-ABC--) includes BCD and B/H feature but not DE
+ found = sq.findFeatures(1, 6);
+ assertEquals(2, found.size());
+ assertTrue(found.contains(sf1));
+ assertTrue(found.contains(sf3));
+
+ // columns 5-6 (--) includes (enclosing) BCD but not (contact) B/H feature
+ found = sq.findFeatures(5, 6);
+ assertEquals(1, found.size());
+ assertTrue(found.contains(sf1));
+
+ // columns 7-10 (DEF-) includes BCD, DE, F/G but not B/H feature
+ found = sq.findFeatures(7, 10);
+ assertEquals(3, found.size());
+ assertTrue(found.contains(sf1));
+ assertTrue(found.contains(sf2));
+ assertTrue(found.contains(sf4));
}
}
import jalview.gui.Preferences;
import jalview.gui.StructureViewer;
import jalview.gui.StructureViewer.ViewerType;
+import jalview.io.DataSourceType;
import jalview.io.FileLoader;
import jalview.structure.StructureMapping;
import jalview.structure.StructureSelectionManager;
import java.io.IOException;
import java.util.List;
import java.util.Vector;
-import jalview.io.DataSourceType;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
binding.copyStructureAttributesToFeatures("phi", af.getViewport()
.getAlignPanel());
fr.setVisible("phi");
- List<SequenceFeature> fs = fr.findFeaturesAtRes(fer2Arath, 54);
+ List<SequenceFeature> fs = fer2Arath.getFeatures().findFeatures(54, 54);
assertEquals(fs.size(), 3);
- assertEquals(fs.get(0).getType(), "RESNUM");
- assertEquals(fs.get(1).getType(), "phi");
- assertEquals(fs.get(2).getType(), "phi");
- assertEquals(fs.get(1).getDescription(), "A"); // chain
- assertEquals(fs.get(2).getDescription(), "B");
- assertEquals(fs.get(1).getScore(), -131.0713f, 0.001f);
- assertEquals(fs.get(2).getScore(), -127.39512, 0.001f);
+ /*
+ * order of returned features is not guaranteed
+ */
+ assertTrue("RESNUM".equals(fs.get(0).getType())
+ || "RESNUM".equals(fs.get(1).getType())
+ || "RESNUM".equals(fs.get(2).getType()));
+ assertTrue(fs.contains(new SequenceFeature("phi", "A", 54, 54,
+ -131.0713f, "Chimera")));
+ assertTrue(fs.contains(new SequenceFeature("phi", "B", 54, 54,
+ -127.39512f, "Chimera")));
/*
* tear down - also in AfterMethod
int res, String featureType)
{
String where = "at position " + res;
- List<SequenceFeature> fs = fr.findFeaturesAtRes(seq, res);
+ List<SequenceFeature> fs = seq.getFeatures().findFeatures(res, res);
+
assertEquals(fs.size(), 2, where);
assertEquals(fs.get(0).getType(), "RESNUM", where);
SequenceFeature sf = fs.get(1);
}
@Test(groups = "Functional")
- public void testFindFeaturesAtRes()
+ public void testFindFeaturesAtColumn()
{
- String seqData = ">s1\nabcdefghijklmnopqrstuvwxyz\n";
+ String seqData = ">s1/4-29\n-ab--cdefghijklmnopqrstuvwxyz\n";
AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
DataSourceType.PASTE);
AlignViewportI av = af.getViewport();
/*
* with no features
*/
- List<SequenceFeature> features = fr.findFeaturesAtRes(seq, 3);
+ List<SequenceFeature> features = fr.findFeaturesAtColumn(seq, 3);
assertTrue(features.isEmpty());
/*
SequenceFeature sf1 = new SequenceFeature("Type1", "Desc", 0, 0, 1f,
"Group"); // non-positional
seq.addSequenceFeature(sf1);
- SequenceFeature sf2 = new SequenceFeature("Type2", "Desc", 5, 15, 1f,
+ SequenceFeature sf2 = new SequenceFeature("Type2", "Desc", 8, 18, 1f,
"Group1");
seq.addSequenceFeature(sf2);
- SequenceFeature sf3 = new SequenceFeature("Type3", "Desc", 5, 15, 1f,
+ SequenceFeature sf3 = new SequenceFeature("Type3", "Desc", 8, 18, 1f,
"Group2");
seq.addSequenceFeature(sf3);
- SequenceFeature sf4 = new SequenceFeature("Type3", "Desc", 5, 15, 1f,
+ SequenceFeature sf4 = new SequenceFeature("Type3", "Desc", 8, 18, 1f,
null); // null group is always treated as visible
seq.addSequenceFeature(sf4);
/*
* add contact features
*/
- SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "Desc", 4,
- 12, 1f, "Group1");
+ SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "Desc", 7,
+ 15, 1f, "Group1");
seq.addSequenceFeature(sf5);
- SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "Desc", 4,
- 12, 1f, "Group2");
+ SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "Desc", 7,
+ 15, 1f, "Group2");
seq.addSequenceFeature(sf6);
- SequenceFeature sf7 = new SequenceFeature("Disulphide Bond", "Desc", 4,
- 12, 1f, null);
+ SequenceFeature sf7 = new SequenceFeature("Disulphide Bond", "Desc", 7,
+ 15, 1f, null);
seq.addSequenceFeature(sf7);
+ // feature spanning B--C
+ SequenceFeature sf8 = new SequenceFeature("Type1", "Desc", 5, 6, 1f,
+ "Group");
+ seq.addSequenceFeature(sf8);
+ // contact feature B/C
+ SequenceFeature sf9 = new SequenceFeature("Disulphide Bond", "Desc", 5,
+ 6, 1f, "Group");
+ seq.addSequenceFeature(sf9);
+
/*
* let feature renderer discover features (and make visible)
*/
fr.findAllFeatures(true);
- features = fr.findFeaturesAtRes(seq, 12); // all positional
+ features = fr.findFeaturesAtColumn(seq, 15); // all positional
assertEquals(features.size(), 6);
assertTrue(features.contains(sf2));
assertTrue(features.contains(sf3));
/*
* at a non-contact position
*/
- features = fr.findFeaturesAtRes(seq, 11);
+ features = fr.findFeaturesAtColumn(seq, 14);
assertEquals(features.size(), 3);
assertTrue(features.contains(sf2));
assertTrue(features.contains(sf3));
data[2] = new Object[] { "Type3", colour, true };
data[3] = new Object[] { "Disulphide Bond", colour, true };
fr.setFeaturePriority(data);
- features = fr.findFeaturesAtRes(seq, 12);
+
+ features = fr.findFeaturesAtColumn(seq, 15);
assertEquals(features.size(), 5); // no sf2
assertTrue(features.contains(sf3));
assertTrue(features.contains(sf4));
* make "Group2" not displayed
*/
fr.setGroupVisibility("Group2", false);
- features = fr.findFeaturesAtRes(seq, 12);
+
+ features = fr.findFeaturesAtColumn(seq, 15);
assertEquals(features.size(), 3); // no sf2, sf3, sf6
assertTrue(features.contains(sf4));
assertTrue(features.contains(sf5));
assertTrue(features.contains(sf7));
+
+ // features 'at' a gap between b and c
+ // - returns enclosing feature BC but not contact feature B/C
+ features = fr.findFeaturesAtColumn(seq, 4);
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf8));
+ features = fr.findFeaturesAtColumn(seq, 5);
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf8));
}
}