X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fanalysis%2FFinder.java;h=181cc9f0639ea6d475b10d46bfa0b93fe37ee24b;hb=13a74c42398c4a2d3794242efec6e52b949b5e5d;hp=5d42905ba40dad454a23b8c1e2ec0a4219cd6cd7;hpb=4016a0a5baf92cea3f1303fdaae3804244857427;p=jalview.git diff --git a/src/jalview/analysis/Finder.java b/src/jalview/analysis/Finder.java index 5d42905..181cc9f 100644 --- a/src/jalview/analysis/Finder.java +++ b/src/jalview/analysis/Finder.java @@ -20,24 +20,27 @@ */ package jalview.analysis; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +import com.stevesoft.pat.Regex; + import jalview.api.AlignViewportI; import jalview.api.FinderI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SearchResultMatchI; import jalview.datamodel.SearchResults; import jalview.datamodel.SearchResultsI; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; +import jalview.datamodel.features.SequenceFeaturesI; import jalview.util.Comparison; import jalview.util.MapList; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import com.stevesoft.pat.Regex; - /** * Implements the search algorithm for the Find dialog */ @@ -97,7 +100,8 @@ public class Finder implements FinderI @Override public void findAll(String theSearchString, boolean matchCase, - boolean searchDescription, boolean ignoreHidden) + boolean searchDescription, boolean searchFeatureDesc, + boolean ignoreHidden) { /* * search from the start @@ -105,8 +109,8 @@ public class Finder implements FinderI sequenceIndex = 0; residueIndex = -1; - doFind(theSearchString, matchCase, searchDescription, true, - ignoreHidden); + doFind(theSearchString, matchCase, searchDescription, searchFeatureDesc, + true, ignoreHidden); /* * reset to start for next search @@ -117,11 +121,12 @@ public class Finder implements FinderI @Override public void findNext(String theSearchString, boolean matchCase, - boolean searchDescription, boolean ignoreHidden) + boolean searchDescription, boolean searchFeatureDesc, + boolean ignoreHidden) { - doFind(theSearchString, matchCase, searchDescription, false, - ignoreHidden); - + doFind(theSearchString, matchCase, searchDescription, searchFeatureDesc, + false, ignoreHidden); + if (searchResults.isEmpty() && idMatches.isEmpty()) { /* @@ -142,13 +147,14 @@ public class Finder implements FinderI * @param ignoreHidden */ protected void doFind(String theSearchString, boolean matchCase, - boolean searchDescription, boolean findAll, boolean ignoreHidden) + boolean searchDescription, boolean searchFeatureDesc, + boolean findAll, boolean ignoreHidden) { searchResults = new SearchResults(); idMatches = new ArrayList<>(); String searchString = matchCase ? theSearchString - : theSearchString.toUpperCase(); + : theSearchString.toUpperCase(Locale.ROOT); Regex searchPattern = new Regex(searchString); searchPattern.setIgnoreCase(!matchCase); @@ -164,21 +170,17 @@ public class Finder implements FinderI getSequence(ignoreHidden); boolean found = false; - while (!found || findAll) + while ((!found || findAll) && sequenceIndex < end) { found = findNextMatch(searchString, searchPattern, searchDescription, - ignoreHidden); - if (sequenceIndex >= end) - { - break; - } + searchFeatureDesc, ignoreHidden); } } /** - * Calculates and saves the sequence string to search. The string is restricted - * to the current selection region if there is one, and is saved with all gaps - * removed. + * Calculates and saves the sequence string to search. The string is + * restricted to the current selection region if there is one, and is saved + * with all gaps removed. *

* If there are hidden columns, and option {@ignoreHidden} is selected, then * only visible positions of the sequence are included, and a mapping is also @@ -250,13 +252,14 @@ public class Finder implements FinderI } /** - * Returns a string consisting of only the visible residues of {@code seq} from - * alignment column {@ fromColumn}, restricted to the current selection region - * if there is one. + * Returns a string consisting of only the visible residues of {@code seq} + * from alignment column {@ fromColumn}, restricted to the current selection + * region if there is one. *

- * As a side-effect, also computes the mapping from the true sequence positions - * to the positions (1, 2, ...) of the returned sequence. This is to allow - * search matches in the visible sequence to be converted to sequence positions. + * As a side-effect, also computes the mapping from the true sequence + * positions to the positions (1, 2, ...) of the returned sequence. This is to + * allow search matches in the visible sequence to be converted to sequence + * positions. * * @param seq * @return @@ -316,9 +319,9 @@ public class Finder implements FinderI /** * Advances the search to the next sequence in the alignment. Sequences not in - * the current selection group (if there is one) are skipped. The (sub-)sequence - * to be searched is extracted, gaps removed, and saved, or set to null if there - * are no more sequences to search. + * the current selection group (if there is one) are skipped. The + * (sub-)sequence to be searched is extracted, gaps removed, and saved, or set + * to null if there are no more sequences to search. *

* Returns true if a sequence could be found, false if end of alignment was * reached @@ -350,8 +353,8 @@ public class Finder implements FinderI * @param ignoreHidden * @return */ - protected boolean findNextMatch(String searchString, - Regex searchPattern, boolean matchDescription, + protected boolean findNextMatch(String searchString, Regex searchPattern, + boolean matchDescription, boolean matchFeatureDesc, boolean ignoreHidden) { if (residueIndex < 0) @@ -360,8 +363,7 @@ public class Finder implements FinderI * at start of sequence; try find by residue number, in sequence id, * or (optionally) in sequence description */ - if (doNonMotifSearches(searchString, searchPattern, - matchDescription)) + if (doNonMotifSearches(searchString, searchPattern, matchDescription)) { return true; } @@ -383,6 +385,11 @@ public class Finder implements FinderI } else { + if (matchFeatureDesc) + { + // TODO - record last matched + matched = searchSequenceFeatures(residueIndex, searchPattern); + } residueIndex = Integer.MAX_VALUE; } } @@ -414,14 +421,14 @@ public class Finder implements FinderI */ int offset = searchPattern.matchedFrom(); int matchStartPosition = this.searchedSequenceStartPosition + offset; - int matchEndPosition = matchStartPosition - + searchPattern.charsMatched() - 1; + int matchEndPosition = matchStartPosition + searchPattern.charsMatched() + - 1; /* * update residueIndex to next position after the start of the match * (findIndex returns a value base 1, columnIndex is held base 0) */ - residueIndex += offset + 1; + residueIndex = searchPattern.matchedFrom() + 1; /* * return false if the match is entirely in a hidden region @@ -449,9 +456,9 @@ public class Finder implements FinderI } /** - * Adds one match to the stored list. If hidden residues are being skipped, then - * the match may need to be split into contiguous positions of the sequence (so - * it does not include skipped residues). + * Adds one match to the stored list. If hidden residues are being skipped, + * then the match may need to be split into contiguous positions of the + * sequence (so it does not include skipped residues). * * @param seq * @param matchStartPosition @@ -475,10 +482,7 @@ public class Finder implements FinderI */ int[] truePositions = searchedSequenceMap .locateInFrom(matchStartPosition, matchEndPosition); - for (int i = 0; i < truePositions.length - 1; i += 2) - { - searchResults.addResult(seq, truePositions[i], truePositions[i + 1]); - } + searchResults.addResult(seq, truePositions); } /** @@ -549,6 +553,35 @@ public class Finder implements FinderI } /** + * Searches for a match with the sequence features, and if found, adds the + * sequence to the list of match ids, (but not as a duplicate). Answers true + * if a match was added, else false. + * + * TODO: allow incremental searching (ie next feature matched after last) + * + * @param seq + * @param searchPattern + * @return + */ + protected boolean searchSequenceFeatures(int from, Regex searchPattern) + { + boolean matched = false; + SequenceI seq = viewport.getAlignment().getSequenceAt(sequenceIndex); + + SequenceFeaturesI sf = seq.getFeatures(); + for (SequenceFeature feature : sf.getAllFeatures(null)) + { + if (searchPattern.search(feature.type) || (feature.description != null + && searchPattern.search(feature.description))) + { + searchResults.addResult(seq, feature.getBegin(), feature.getEnd()); + matched = true; + } + } + return matched; + } + + /** * Searches for a match with the sequence description, and if found, adds the * sequence to the list of match ids (but not as a duplicate). Answers true if * a match was added, else false. @@ -557,10 +590,12 @@ public class Finder implements FinderI * @param searchPattern * @return */ - protected boolean searchSequenceDescription(SequenceI seq, Regex searchPattern) + protected boolean searchSequenceDescription(SequenceI seq, + Regex searchPattern) { String desc = seq.getDescription(); - if (desc != null && searchPattern.search(desc) && !idMatches.contains(seq)) + if (desc != null && searchPattern.search(desc) + && !idMatches.contains(seq)) { idMatches.add(seq); return true; @@ -589,7 +624,8 @@ public class Finder implements FinderI /** * If the residue position is valid for the sequence, and in a visible column, - * adds the position to the search results and returns true, else answers false. + * adds the position to the search results and returns true, else answers + * false. * * @param seq * @param resNo @@ -622,7 +658,8 @@ public class Finder implements FinderI return true; } int col = seq.findIndex(res); // base 1 - return viewport.getAlignment().getHiddenColumns().isVisible(col - 1); // base 0 + return viewport.getAlignment().getHiddenColumns().isVisible(col - 1); // base + // 0 } @Override