*/
protected void updateCursor(int residuePos, int column, int startColumn)
{
- int endColumn = cursor == null ? 0 : cursor.lastColumnPosition;
+ /*
+ * preserve end residue column provided cursor was valid
+ */
+ int endColumn = isValidCursor(cursor) ? cursor.lastResidueColumn : 0;
if (residuePos == this.end)
{
endColumn = column;
/*
* move left or right to find pos from hint.position
*/
- int col = curs.columnPosition - 1; // convert from base 1 to 0-based array
- // index
+ int col = curs.columnPosition - 1; // convert from base 1 to base 0
int newPos = curs.residuePosition;
int delta = newPos > pos ? -1 : 1;
}
col++; // convert back to base 1
- updateCursor(pos, col, curs.firstColumnPosition);
+ updateCursor(pos, col, curs.firstResidueColumn);
return col;
}
* {@inheritDoc}
*/
@Override
+ public Range findPositions(int fromColumn, int toColumn)
+ {
+ if (toColumn < fromColumn || fromColumn < 1)
+ {
+ return null;
+ }
+
+ /*
+ * find the first non-gapped position, if any
+ */
+ int firstPosition = 0;
+ int col = fromColumn - 1;
+ int length = sequence.length;
+ while (col < length && col < toColumn)
+ {
+ if (!Comparison.isGap(sequence[col]))
+ {
+ firstPosition = findPosition(col++);
+ break;
+ }
+ col++;
+ }
+
+ if (firstPosition == 0)
+ {
+ return null;
+ }
+
+ /*
+ * find the last non-gapped position
+ */
+ int lastPosition = firstPosition;
+ while (col < length && col < toColumn)
+ {
+ if (!Comparison.isGap(sequence[col++]))
+ {
+ lastPosition++;
+ }
+ }
+
+ return new Range(firstPosition, lastPosition);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public int findPosition(final int column)
{
/*
return curs.residuePosition; // easy case :-)
}
- if (curs.lastColumnPosition > 0 && curs.lastColumnPosition < col)
+ if (curs.lastResidueColumn > 0 && curs.lastResidueColumn < col)
{
/*
* sequence lies entirely to the left of col
return end + 1;
}
- if (curs.firstColumnPosition > 0 && curs.firstColumnPosition > col)
+ if (curs.firstResidueColumn > 0 && curs.firstResidueColumn > col)
{
/*
* sequence lies entirely to the right of col
/*
* move left or right to find pos from cursor position
*/
- int firstResidueColumn = curs.firstColumnPosition;
+ int firstResidueColumn = curs.firstResidueColumn;
int column = curs.columnPosition - 1; // to base 0
int newPos = curs.residuePosition;
int delta = curs.columnPosition > col ? -1 : 1;
// the very large sequence case
int eindex = -1, sindex = -1;
boolean ecalc = false, scalc = false;
- for (int s = i; s < j; s++)
+ for (int s = i; s < j && s < sequence.length; s++)
{
- if (jalview.schemes.ResidueProperties.aaIndex[sequence[s]] != 23)
+ if (!Comparison.isGap(sequence[s]))
{
if (createNewDs)
{
{
int startPos = findPosition(fromColumn - 1); // convert base 1 to base 0
int endPos = findPosition(toColumn - 1);
- // to trace / debug behaviour:
- // System.out
- // .println(String
- // .format("%s.findFeatures columns [%d-%d] positions [%d-%d] leaves cursor %s",
- // getName(), fromColumn, toColumn, startPos,
- // endPos, cursor));
+
List<SequenceFeature> result = new ArrayList<>();
if (datasetSequence != null)
{
/*
* 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
+ * remove any that are not enclosing features
*/
if (endPos > this.end || Comparison.isGap(sequence[fromColumn - 1])
|| Comparison.isGap(sequence[toColumn - 1]))
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)
+ if (featureStartColumn > toColumn
+ || featureEndColumn < fromColumn)
{
it.remove();
}
return count;
}
-
- @Override
- public List<SequenceFeature[]> adjustFeatures(int fromColumn, int toColumn)
- {
- List<SequenceFeature[]> amended = new ArrayList<>();
-
- if (toColumn < fromColumn)
- {
- return amended;
- }
-
- synchronized (sequenceFeatureStore)
- {
- /*
- * get features that overlap or span the cut region
- */
- List<SequenceFeature> overlaps = findFeatures(fromColumn, toColumn);
- int cutWidth = toColumn - fromColumn + 1;
-
- /*
- * get features that strictly follow the cut region,
- * and shift them left by the width of the cut
- */
- List<SequenceFeature> follow = findFeatures(toColumn + 1,
- Integer.MAX_VALUE);
- follow.removeAll(overlaps);
- for (SequenceFeature sf : follow)
- {
- SequenceFeature copy = new SequenceFeature(sf, sf.getBegin()
- - cutWidth, sf.getEnd() - cutWidth, sf.getFeatureGroup(),
- sf.getScore());
- deleteFeature(sf);
- addSequenceFeature(copy);
- }
-
- /*
- * adjust start-end of overlapping features, and delete if enclosed by
- * the cut, or a partially overlapping contact feature
- */
- for (SequenceFeature sf : overlaps)
- {
- // TODO recode to compute newBegin, newEnd, isDelete
- // then perform the action
- int sfBegin = sf.getBegin();
- int sfEnd = sf.getEnd();
- int startCol = findIndex(sfBegin);
- int endCol = findIndex(sfEnd);
- if (startCol >= fromColumn && endCol <= toColumn)
- {
- // within cut region - delete feature
- deleteFeature(sf);
- amended.add(new SequenceFeature[] { sf, null });
- continue;
- }
- if (startCol < fromColumn && endCol > toColumn)
- {
- // feature spans cut region - shift end left
- SequenceFeature copy = new SequenceFeature(sf, sf.getBegin(),
- sf.getEnd() - cutWidth, sf.getFeatureGroup(),
- sf.getScore());
- deleteFeature(sf);
- addSequenceFeature(copy);
- amended.add(new SequenceFeature[] { sf, copy });
- continue;
- }
- // todo partial overlap - delete if contact feature
- }
- }
-
- return amended;
- }
}