X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FSequence.java;h=24f904cf8f00bbe72c62c62a3ccad57e3ee66fb8;hb=70a93ebbabd80e25c60a0e6444013ed4260b09a5;hp=cc4a0dca39ce909e4b3eb97f7029f903fce14aa6;hpb=bf1f3d11a1915e63b11852a1eb63824f984a4342;p=jalview.git diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index cc4a0dc..24f904c 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -664,19 +664,16 @@ public class Sequence extends ASequence implements SequenceI return this.description; } - /* - * (non-Javadoc) - * - * @see jalview.datamodel.SequenceI#findIndex(int) + /** + * {@inheritDoc} */ @Override public int findIndex(int pos) { /* - * use a valid nearby cursor if available + * use a valid, hopefully nearby, cursor if available */ - if (cursor != null && cursor.sequence == this - && cursor.token == changeCount) + if (isValidCursor(cursor)) { return findIndex(pos, cursor); } @@ -693,20 +690,25 @@ public class Sequence extends ASequence implements SequenceI i++; } - if ((j == end) && (j < pos)) + if (j == end && j < pos) { return end + 1; } - else - { - updateCursor(pos, i); - return i; - } + + updateCursor(pos, i); + return i; } + /** + * Updates the cursor to the latest found residue and column position + * + * @param residuePos + * (start..) + * @param column + * (1..) + */ protected void updateCursor(int residuePos, int column) { - // TODO probably want to synchronize this on something cursor = new SequenceCursor(this, residuePos, column, this.changeCount); } @@ -721,7 +723,7 @@ public class Sequence extends ASequence implements SequenceI */ protected int findIndex(int pos, SequenceCursor curs) { - if (curs.sequence != this || curs.token != changeCount) + if (!isValidCursor(curs)) { /* * wrong or invalidated cursor, compute de novo @@ -761,40 +763,93 @@ public class Sequence extends ASequence implements SequenceI return col; } + /** + * {@inheritDoc} + */ @Override - public int findPosition(final int i) + public int findPosition(final int column) { /* - * use a valid nearby cursor if available + * use a valid, hopefully nearby, cursor if available */ - if (cursor != null && cursor.sequence == this - && cursor.token == changeCount) + if (isValidCursor(cursor)) { - return findPosition(i + 1, cursor); + return findPosition(column + 1, cursor); + } + + // TODO recode this more naturally i.e. count residues only + // as they are found, not 'in anticipation' + + int lastPosFound = 0; + int lastPosFoundColumn = 0; + int seqlen = sequence.length; + if (seqlen > 0 && !Comparison.isGap(sequence[0])) + { + lastPosFound = start; + lastPosFoundColumn = 0; } int j = 0; int pos = start; - int seqlen = sequence.length; - while ((j < i) && (j < seqlen)) + + while (j < column && j < seqlen) { if (!Comparison.isGap(sequence[j])) { + lastPosFound = pos; + lastPosFoundColumn = j; pos++; } - j++; } + if (j < seqlen && !Comparison.isGap(sequence[j])) + { + lastPosFound = pos; + lastPosFoundColumn = j; + } - if (j == i && !Comparison.isGap(sequence[i])) + /* + * update the cursor to the last residue position found (if any) + * (converting column position to base 1) + */ + if (lastPosFound != 0) { - updateCursor(pos, i + 1); + updateCursor(lastPosFound, lastPosFoundColumn + 1); } return pos; } /** + * Answers true if the given cursor is not null, is for this sequence object, + * and has a token value that matches this object's changeCount, else false. + * This allows us to ignore a cursor as 'stale' if the sequence has been + * modified since the cursor was created. + * + * @param curs + * @return + */ + protected boolean isValidCursor(SequenceCursor curs) + { + if (curs == null || curs.sequence != this || curs.token != changeCount) + { + return false; + } + /* + * sanity check against range + */ + if (curs.columnPosition < 0 || curs.columnPosition >= sequence.length) + { + return false; + } + if (curs.residuePosition < start || curs.residuePosition > end) + { + return false; + } + return true; + } + + /** * Answers the sequence position (start..) for the given aligned column * position (1..), given a hint of a cursor in the neighbourhood. The cursor * may lie left of, at, or to the right of the column position. @@ -805,7 +860,7 @@ public class Sequence extends ASequence implements SequenceI */ protected int findPosition(final int col, SequenceCursor curs) { - if (curs.sequence != this || curs.token != changeCount) + if (!isValidCursor(curs)) { /* * wrong or invalidated cursor, compute de novo @@ -815,6 +870,7 @@ public class Sequence extends ASequence implements SequenceI if (curs.columnPosition == col) { + cursor = curs; // in case this method becomes public return curs.residuePosition; // easy case :-) } @@ -825,6 +881,8 @@ public class Sequence extends ASequence implements SequenceI int newPos = curs.residuePosition; int delta = curs.columnPosition > col ? -1 : 1; boolean gapped = false; + int lastFoundPosition = curs.residuePosition; + int lastFoundPositionColumn = curs.columnPosition; while (column != col - 1) { @@ -837,14 +895,21 @@ public class Sequence extends ASequence implements SequenceI if (!gapped) { newPos += delta; + lastFoundPosition = newPos; + lastFoundPositionColumn = column + 1; } } + if (cursor == null || lastFoundPosition != cursor.residuePosition) + { + updateCursor(lastFoundPosition, lastFoundPositionColumn); + } + /* * hack to give position to the right if on a gap - * pending resolution of JAL-2562 + * or beyond the length of the sequence (see JAL-2562) */ - if (delta > 0 && gapped) + if (delta > 0 && (gapped || column >= sequence.length)) { newPos++; } @@ -934,7 +999,7 @@ public class Sequence extends ASequence implements SequenceI */ protected Range findPositions(int fromCol, int toCol, SequenceCursor curs) { - if (curs.sequence != this || curs.token != changeCount) + if (!isValidCursor(curs)) { /* * wrong or invalidated cursor, compute de novo