<mapID target="biojson" url="html/features/bioJsonFormat.html" />
<mapID target="pdbfetcher" url="html/features/pdbsequencefetcher.html" />
+ <mapID target="pdbfts" url="html/features/pdbsequencefetcher.html#pdbfts" />
<mapID target="siftsmapping" url="html/features/siftsmapping.html" />
<mapID target="pdbchooser" url="html/features/structurechooser.html" />
<mapID target="selectcolbyannot" url="html/features/columnFilterByAnnotation.html" />
<mapID target="ensemblfetch" url="html/features/ensemblsequencefetcher.html" />
<mapID target="uniprotfetcher" url="html/features/uniprotsequencefetcher.html" />
+ <mapID target="uniprotfts" url="html/features/uniprotsequencefetcher.html#uniprotfts" />
<mapID target="urllinks" url="html/webServices/urllinks.html" />
<mapID target="linksprefs" url="html/features/preferences.html#links" />
alt="PDB sequence fetcher (introduced in Jalview 2.9)" />
<p>
- <strong>Searching the PDB Database</strong>
+ <a name="pdbfts"><strong>Searching the PDB Database</strong></a>
</p>
<p>To search the PDB, begin typing in the text box. If the
'autosearch' checkbox is enabled, then the results of your query
</p>
<p>
- <strong>Searching the UniProt Database</strong>
+ <a name="uniprotfts"><strong>Searching the UniProt Database</strong></a>
</p>
<p>To search UniProt, simply begin typing in the text box. If the
'autosearch' check box is enabled, then after a short delay (about
*/
package jalview.analysis;
+import jalview.api.AlignViewportI;
+import jalview.api.FinderI;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Range;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
+import jalview.datamodel.VisibleContigsIterator;
import jalview.util.Comparison;
-import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import com.stevesoft.pat.Regex;
-public class Finder
+/**
+ * Implements the search algorithm for the Find dialog
+ */
+public class Finder implements FinderI
{
- /**
- * Implements the search algorithms for the Find dialog box.
+ /*
+ * matched residue locations
*/
- SearchResultsI searchResults;
+ private SearchResultsI searchResults;
- AlignmentI alignment;
+ /*
+ * sequences matched by id or description
+ */
+ private Vector<SequenceI> idMatches;
- SequenceGroup selection = null;
+ /*
+ * the viewport to search over
+ */
+ private AlignViewportI viewport;
- Vector<SequenceI> idMatch = null;
+ /*
+ * sequence index in alignment to search from
+ */
+ private int sequenceIndex;
- boolean caseSensitive = false;
+ /*
+ * column position in sequence to search from, base 0
+ * - absolute column number including any hidden columns
+ * (position after start of last match for a repeat search)
+ */
+ private int columnIndex;
- private boolean includeDescription = false;
+ /**
+ * Constructor for searching a viewport
+ *
+ * @param av
+ */
+ public Finder(AlignViewportI av)
+ {
+ this.viewport = av;
+ this.sequenceIndex = 0;
+ this.columnIndex = -1;
+ }
- boolean findAll = false;
+ @Override
+ public void findAll(String theSearchString, boolean matchCase,
+ boolean searchDescription)
+ {
+ /*
+ * search from the start
+ */
+ sequenceIndex = 0;
+ columnIndex = -1;
- Regex regex = null;
+ doFind(theSearchString, matchCase, searchDescription, true);
- /**
- * holds last-searched position between calls to find(false)
- */
- int seqIndex = 0, resIndex = -1;
+ /*
+ * reset to start for next search
+ */
+ sequenceIndex = 0;
+ columnIndex = -1;
+ }
- public Finder(AlignmentI alignment, SequenceGroup selection)
+ @Override
+ public void findNext(String theSearchString, boolean matchCase,
+ boolean searchDescription)
{
- this.alignment = alignment;
- this.selection = selection;
+ doFind(theSearchString, matchCase, searchDescription, false);
+
+ if (searchResults.isEmpty() && idMatches.isEmpty())
+ {
+ /*
+ * search failed - reset to start for next search
+ */
+ sequenceIndex = 0;
+ columnIndex = -1;
+ }
}
/**
- * restart search at given sequence and residue on alignment and (optionally)
- * contained in selection
+ * Performs a 'find next' or 'find all'
*
- * @param alignment
- * @param selectionGroup
- * @param seqIndex
- * @param resIndex
+ * @param theSearchString
+ * @param matchCase
+ * @param searchDescription
+ * @param findAll
*/
- public Finder(AlignmentI alignment, SequenceGroup selectionGroup,
- int seqIndex, int resIndex)
+ protected void doFind(String theSearchString, boolean matchCase,
+ boolean searchDescription, boolean findAll)
{
- this(alignment, selectionGroup);
- this.seqIndex = seqIndex;
- this.resIndex = resIndex;
- }
+ String searchString = matchCase ? theSearchString
+ : theSearchString.toUpperCase();
+ Regex searchPattern = new Regex(searchString);
+ searchPattern.setIgnoreCase(!matchCase);
- public boolean find(String searchString)
- {
- boolean hasResults = false;
- if (!caseSensitive)
- {
- searchString = searchString.toUpperCase();
- }
- regex = new Regex(searchString);
- regex.setIgnoreCase(!caseSensitive);
searchResults = new SearchResults();
- idMatch = new Vector<SequenceI>();
- String item = null;
- boolean found = false;
- int end = alignment.getHeight();
+ idMatches = new Vector<>();
- // /////////////////////////////////////////////
-
- if (selection != null)
+ SequenceGroup selection = viewport.getSelectionGroup();
+ if (selection != null && selection.getSize() < 1)
{
- if ((selection.getSize() < 1)
- || ((selection.getEndRes() - selection.getStartRes()) < 2))
- {
- selection = null;
- }
+ selection = null; // ? ignore column-only selection
}
- SearchResultMatchI lastm = null;
- while (!found && (seqIndex < end))
- {
- SequenceI seq = alignment.getSequenceAt(seqIndex);
+ AlignmentI alignment = viewport.getAlignment();
+ int end = alignment.getHeight();
- if ((selection != null && selection.getSize() > 0)
- && !selection.getSequences(null).contains(seq))
+ while (sequenceIndex < end)
+ {
+ SequenceI seq = alignment.getSequenceAt(sequenceIndex);
+ boolean found = findNextMatch(seq, searchString, searchPattern,
+ searchDescription);
+ if (found && !findAll)
{
- seqIndex++;
- resIndex = -1;
-
- continue;
+ return;
}
- if (resIndex < 0)
+ if (!found)
{
- resIndex = 0;
- // test for one off matches - sequence position and sequence ID
- // //// is the searchString a residue number?
- try
- {
- int res = Integer.parseInt(searchString);
- // possibly a residue number - check if valid for seq
- if (seq.getEnd() >= res)
- {
- searchResults.addResult(seq, res, res);
- hasResults = true;
- // resIndex=seq.getLength();
- // seqIndex++;
- if (!findAll)
- {
- found = true;
- break;
- }
- }
- } catch (NumberFormatException ex)
- {
- }
-
- if (regex.search(seq.getName()) && !idMatch.contains(seq))
- {
- idMatch.addElement(seq);
- hasResults = true;
- if (!findAll)
- {
- // stop and return the match
- found = true;
- break;
- }
- }
-
- if (isIncludeDescription() && seq.getDescription() != null
- && regex.search(seq.getDescription())
- && !idMatch.contains(seq))
- {
- idMatch.addElement(seq);
- hasResults = true;
- if (!findAll)
- {
- // stop and return the match
- found = true;
- break;
- }
- }
+ sequenceIndex++;
+ columnIndex = -1;
}
- item = seq.getSequenceAsString();
+ }
+ }
- if ((selection != null)
- && (selection.getEndRes() < alignment.getWidth() - 1))
- {
- item = item.substring(0, selection.getEndRes() + 1);
- }
+ /**
+ * Answers the start-end column range of the visible region of
+ * <code>sequence</code> starting at or after the given <code>column</code>.
+ * If there are no hidden columns, this just returns the remaining width of
+ * the sequence. The range is restricted to the current <code>selection</code>
+ * if there is one. Answers null if there are no visible columns at or after
+ * <code>column</code>.
+ */
+ protected Range getNextVisibleSequenceRegion(SequenceI sequence,
+ int column)
+ {
+ int seqColStart = column;
+ int seqColEnd = sequence.getLength() - 1;
- // /Shall we ignore gaps???? - JBPNote: Add Flag for forcing this or not
- StringBuilder noGapsSB = new StringBuilder();
- int insertCount = 0;
- List<Integer> spaces = new ArrayList<Integer>();
+ /*
+ * restrict search to (next) visible column region,
+ * in case there are hidden columns
+ */
+ AlignmentI alignment = viewport.getAlignment();
+ VisibleContigsIterator visibleRegions = alignment.getHiddenColumns()
+ .getVisContigsIterator(column, alignment.getWidth(),
+ false);
+ int[] visible = visibleRegions.hasNext() ? visibleRegions.next() : null;
+ if (visible == null)
+ {
+ columnIndex = seqColEnd + 1;
+ return null;
+ }
+ seqColStart = Math.max(seqColStart, visible[0]);
+ seqColEnd = Math.min(seqColEnd, visible[1]);
- for (int j = 0; j < item.length(); j++)
+ /*
+ * restrict search to selected region if there is one
+ */
+ SequenceGroup selection = viewport.getSelectionGroup();
+ if (selection != null)
+ {
+ int selectionStart = selection.getStartRes();
+ int selectionEnd = selection.getEndRes();
+ if (selectionStart > seqColEnd || selectionEnd < seqColStart)
{
- if (!Comparison.isGap(item.charAt(j)))
- {
- noGapsSB.append(item.charAt(j));
- spaces.add(Integer.valueOf(insertCount));
- }
- else
- {
- insertCount++;
- }
+ /*
+ * sequence region doesn't overlap selection region
+ */
+ columnIndex = seqColEnd + 1;
+ return null;
}
+ seqColStart = Math.max(seqColStart, selectionStart);
+ seqColEnd = Math.min(seqColEnd, selectionEnd);
+ }
- String noGaps = noGapsSB.toString();
- for (int r = resIndex; r < noGaps.length(); r++)
- {
+ return new Range(seqColStart, seqColEnd);
+ }
- if (regex.searchFrom(noGaps, r))
- {
- resIndex = regex.matchedFrom();
-
- if ((selection != null && selection.getSize() > 0) && (resIndex
- + spaces.get(resIndex) < selection.getStartRes()))
- {
- continue;
- }
- // if invalid string used, then regex has no matched to/from
- int sres = seq.findPosition(resIndex + spaces.get(resIndex));
- int eres = seq.findPosition(regex.matchedTo() - 1
- + (spaces.get(regex.matchedTo() - 1)));
- // only add result if not contained in previous result
- if (lastm == null || (lastm.getSequence() != seq
- || (!(lastm.getStart() <= sres
- && lastm.getEnd() >= eres))))
- {
- lastm = searchResults.addResult(seq, sres, eres);
- }
- hasResults = true;
- if (!findAll)
- {
- // thats enough, break and display the result
- found = true;
- resIndex++;
-
- break;
- }
-
- r = resIndex;
- }
- else
- {
- break;
- }
- }
+ /**
+ * Finds the next match in the given sequence, starting at column at
+ * <code>columnIndex</code>. Answers true if a match is found, else false. If
+ * a match is found, <code>columnIndex</code> is advanced to the column after
+ * the start of the matched region, ready for a search from the next position.
+ *
+ * @param seq
+ * @param searchString
+ * @param searchPattern
+ * @param matchDescription
+ * @return
+ */
+ protected boolean findNextMatch(SequenceI seq, String searchString,
+ Regex searchPattern, boolean matchDescription)
+ {
+ SequenceGroup selection = viewport.getSelectionGroup();
+ if (selection != null && !selection.contains(seq))
+ {
+ /*
+ * this sequence is not in the selection - advance to next sequence
+ */
+ return false;
+ }
- if (!found)
+ if (columnIndex < 0)
+ {
+ /*
+ * at start of sequence; try find by residue number, in sequence id,
+ * or (optionally) in sequence description
+ */
+ if (doNonMotifSearches(seq, searchString, searchPattern,
+ matchDescription))
{
- seqIndex++;
- resIndex = -1;
+ return true;
}
}
- /**
- * We now search the Id string in the main search loop. for (int id = 0; id
- * < alignment.getHeight(); id++) { if
- * (regex.search(alignment.getSequenceAt(id).getName())) {
- * idMatch.addElement(alignment.getSequenceAt(id)); hasResults = true; } }
+ /*
+ * search for next match in sequence string
*/
- return hasResults;
- }
-
- /**
- * @return the alignment
- */
- public AlignmentI getAlignment()
- {
- return alignment;
+ int end = seq.getLength();
+ while (columnIndex < end)
+ {
+ if (searchNextVisibleRegion(seq, searchPattern))
+ {
+ return true;
+ }
+ }
+ return false;
}
/**
- * @param alignment
- * the alignment to set
+ * Searches the sequence, starting from <code>columnIndex</code>, and adds the
+ * next match (if any) to <code>searchResults</code>. The search is restricted
+ * to the next visible column region, and to the <code>selection</code> region
+ * if there is one. Answers true if a match is added, else false.
+ *
+ * @param seq
+ * @param searchPattern
+ * @return
*/
- public void setAlignment(AlignmentI alignment)
+ protected boolean searchNextVisibleRegion(SequenceI seq, Regex searchPattern)
{
- this.alignment = alignment;
- }
+ Range visible = getNextVisibleSequenceRegion(seq, columnIndex);
+ if (visible == null)
+ {
+ return false;
+ }
+ String seqString = seq.getSequenceAsString(visible.start, visible.end + 1);
+ String noGaps = AlignSeq.extractGaps(Comparison.GapChars, seqString);
- /**
- * @return the caseSensitive
- */
- public boolean isCaseSensitive()
- {
- return caseSensitive;
- }
+ if (searchPattern.search(noGaps))
+ {
+ int sequenceStartPosition = seq.findPosition(visible.start);
+ recordMatch(seq, searchPattern, sequenceStartPosition);
+ return true;
+ }
+ else
+ {
+ /*
+ * no match - advance columnIndex past this visible region
+ * so the next visible region (if any) is searched next
+ */
+ columnIndex = visible.end + 1;
+ }
- /**
- * @param caseSensitive
- * the caseSensitive to set
- */
- public void setCaseSensitive(boolean caseSensitive)
- {
- this.caseSensitive = caseSensitive;
+ return false;
}
/**
- * @return the findAll
+ * Adds the match held in the <code>searchPattern</code> Regex to the
+ * <code>searchResults</code>, unless it is a subregion of the last match
+ * recorded. <code>columnIndex</code> is advanced to the position after the
+ * start of the matched region, ready for the next search. Answers true if a
+ * match was added, else false.
+ *
+ * @param seq
+ * @param searchPattern
+ * @param firstResiduePosition
+ * @return
*/
- public boolean isFindAll()
+ protected boolean recordMatch(SequenceI seq, Regex searchPattern,
+ int firstResiduePosition)
{
- return findAll;
- }
+ /*
+ * get start/end of the match in sequence coordinates
+ */
+ int offset = searchPattern.matchedFrom();
+ int matchStartPosition = firstResiduePosition + offset;
+ int matchEndPosition = matchStartPosition
+ + searchPattern.charsMatched() - 1;
+
+ /*
+ * update columnIndex to next column after the start of the match
+ * (findIndex returns a value base 1, columnIndex is held base 0)
+ */
+ columnIndex = seq.findIndex(matchStartPosition);
- /**
- * @param findAll
- * the findAll to set
- */
- public void setFindAll(boolean findAll)
- {
- this.findAll = findAll;
- }
+ /*
+ * check that this match is not a subset of the previous one (JAL-2302)
+ */
+ List<SearchResultMatchI> matches = searchResults.getResults();
+ SearchResultMatchI lastMatch = matches.isEmpty() ? null
+ : matches.get(matches.size() - 1);
- /**
- * @return the selection
- */
- public jalview.datamodel.SequenceGroup getSelection()
- {
- return selection;
- }
+ if (lastMatch == null || !lastMatch.contains(seq, matchStartPosition,
+ matchEndPosition))
+ {
+ searchResults.addResult(seq, matchStartPosition, matchEndPosition);
+ return true;
+ }
- /**
- * @param selection
- * the selection to set
- */
- public void setSelection(jalview.datamodel.SequenceGroup selection)
- {
- this.selection = selection;
+ return false;
}
/**
- * Returns the (possibly empty) list of matching sequences (when search
- * includes searching sequence names)
+ * Does searches other than for residue patterns. Currently this includes
+ * <ul>
+ * <li>find residue by position (if search string is a number)</li>
+ * <li>match search string to sequence id</li>
+ * <li>match search string to sequence description (optional)</li>
+ * </ul>
+ * Answers true if a match is found, else false.
*
+ * @param seq
+ * @param searchString
+ * @param searchPattern
+ * @param includeDescription
* @return
*/
- public Vector<SequenceI> getIdMatch()
+ protected boolean doNonMotifSearches(SequenceI seq, String searchString,
+ Regex searchPattern, boolean includeDescription)
{
- return idMatch;
- }
+ /*
+ * position sequence search to start of sequence
+ */
+ columnIndex = 0;
- /**
- * @return the regex
- */
- public com.stevesoft.pat.Regex getRegex()
- {
- return regex;
+ if (searchForResidueNumber(seq, searchString))
+ {
+ return true;
+ }
+ if (searchSequenceName(seq, searchPattern))
+ {
+ return true;
+ }
+ if (includeDescription && searchSequenceDescription(seq, searchPattern))
+ {
+ return true;
+ }
+ return false;
}
/**
- * @return the searchResults
+ * 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.
+ *
+ * @param seq
+ * @param searchPattern
+ * @return
*/
- public SearchResultsI getSearchResults()
+ protected boolean searchSequenceDescription(SequenceI seq, Regex searchPattern)
{
- return searchResults;
+ String desc = seq.getDescription();
+ if (desc != null && searchPattern.search(desc) && !idMatches.contains(seq))
+ {
+ idMatches.addElement(seq);
+ return true;
+ }
+ return false;
}
/**
- * @return the resIndex
+ * Searches for a match with the sequence name, 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.
+ *
+ * @param seq
+ * @param searchPattern
+ * @return
*/
- public int getResIndex()
+ protected boolean searchSequenceName(SequenceI seq, Regex searchPattern)
{
- return resIndex;
+ if (searchPattern.search(seq.getName()) && !idMatches.contains(seq))
+ {
+ idMatches.addElement(seq);
+ return true;
+ }
+ return false;
}
/**
- * @param resIndex
- * the resIndex to set
+ * Tries to interpret the search string as a residue position, and if valid,
+ * adds the position to the search results and returns true, else answers
+ * false
*/
- public void setResIndex(int resIndex)
+ protected boolean searchForResidueNumber(SequenceI seq, String searchString)
{
- this.resIndex = resIndex;
+ try
+ {
+ int res = Integer.parseInt(searchString);
+ if (seq.getStart() <= res && seq.getEnd() >= res)
+ {
+ searchResults.addResult(seq, res, res);
+ return true;
+ }
+ } catch (NumberFormatException ex)
+ {
+ }
+ return false;
}
- /**
- * @return the seqIndex
+ /* (non-Javadoc)
+ * @see jalview.analysis.FinderI#getIdMatch()
*/
- public int getSeqIndex()
+ @Override
+ public Vector<SequenceI> getIdMatches()
{
- return seqIndex;
+ return idMatches;
}
- /**
- * @param seqIndex
- * the seqIndex to set
+ /* (non-Javadoc)
+ * @see jalview.analysis.FinderI#getSearchResults()
*/
- public void setSeqIndex(int seqIndex)
- {
- this.seqIndex = seqIndex;
- }
-
- public boolean isIncludeDescription()
- {
- return includeDescription;
- }
-
- public void setIncludeDescription(boolean includeDescription)
+ @Override
+ public SearchResultsI getSearchResults()
{
- this.includeDescription = includeDescription;
+ return searchResults;
}
}
--- /dev/null
+package jalview.api;
+
+import jalview.datamodel.SearchResultsI;
+import jalview.datamodel.SequenceI;
+
+import java.util.List;
+
+/**
+ * An interface for searching for a pattern in an aligment
+ */
+public interface FinderI
+{
+
+ /**
+ * Performs a find for the given search string (interpreted as a regular
+ * expression). Search may optionally be case-sensitive, and may optionally
+ * including match in sequence description (sequence id is always searched).
+ * If the viewport has an active selection, then the find is restricted to the
+ * selection region. Sequences matched by id or description can be retrieved
+ * by getIdMatches(), and matched residue patterns by getSearchResults().
+ *
+ * @param theSearchString
+ * @param caseSensitive
+ * @param searchDescription
+ * @return
+ */
+ void findAll(String theSearchString, boolean caseSensitive,
+ boolean searchDescription);
+
+ /**
+ * Finds the next match for the given search string (interpreted as a regular
+ * expression), starting from the position after the last match found. Search
+ * may optionally be case-sensitive, and may optionally including match in
+ * sequence description (sequence id is always searched). If the viewport has
+ * an active selection, then the find is restricted to the selection region.
+ * Sequences matched by id or description can be retrieved by getIdMatches(),
+ * and matched residue patterns by getSearchResults().
+ *
+ * @param theSearchString
+ * @param caseSensitive
+ * @param searchDescription
+ * @return
+ */
+ void findNext(String theSearchString, boolean caseSensitive,
+ boolean searchDescription);
+
+ /**
+ * Returns the (possibly empty) list of sequences matched on sequence name or
+ * description
+ *
+ * @return
+ */
+ List<SequenceI> getIdMatches();
+
+ /**
+ * Answers the search results (possibly empty) from the last search
+ *
+ * @return
+ */
+ SearchResultsI getSearchResults();
+
+}
\ No newline at end of file
*/
package jalview.appletgui;
+import jalview.api.AlignViewportI;
+import jalview.api.FinderI;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.util.MessageManager;
-import jalview.viewmodel.AlignmentViewport;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
-import java.util.Vector;
+import java.util.Map;
public class Finder extends Panel implements ActionListener
{
- AlignmentViewport av;
+ private AlignViewportI av;
- AlignmentPanel ap;
+ private AlignmentPanel ap;
- Frame frame;
+ private TextField textfield = new TextField();
- SearchResultsI searchResults;
+ private Button findAll = new Button();
- int seqIndex = 0;
+ private Button findNext = new Button();
- int resIndex = -1;
+ private Button createFeatures = new Button();
+
+ private Checkbox caseSensitive = new Checkbox();
+
+ private Checkbox searchDescription = new Checkbox();
+
+ private SearchResultsI searchResults;
+
+ /*
+ * Finder agent per viewport searched
+ */
+ Map<AlignViewportI, FinderI> finders;
public Finder(final AlignmentPanel ap)
{
+ finders = new HashMap<>();
+
try
{
jbInit();
this.av = ap.av;
this.ap = ap;
- frame = new Frame();
+ Frame frame = new Frame();
frame.add(this);
jalview.bin.JalviewLite.addFrame(frame,
MessageManager.getString("action.find"), 340, 120);
else if (evt.getSource() == findAll)
{
- resIndex = -1;
- seqIndex = 0;
doSearch(true);
}
- else if (evt.getSource() == createNewGroup)
+ else if (evt.getSource() == createFeatures)
{
- createNewGroup_actionPerformed();
+ createFeatures_actionPerformed();
}
}
- public void createNewGroup_actionPerformed()
+ public void createFeatures_actionPerformed()
{
- List<SequenceI> seqs = new ArrayList<SequenceI>();
- List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+ List<SequenceI> seqs = new ArrayList<>();
+ List<SequenceFeature> features = new ArrayList<>();
String searchString = textfield.getText().trim();
for (SearchResultMatchI match : searchResults.getResults())
}
}
- void doSearch(boolean findAll)
+ void doSearch(boolean doFindAll)
{
if (ap.av.applet.currentAlignFrame != null)
{
ap = ap.av.applet.currentAlignFrame.alignPanel;
av = ap.av;
}
- createNewGroup.setEnabled(false);
- jalview.analysis.Finder finder = new jalview.analysis.Finder(
- av.getAlignment(), av.getSelectionGroup(), seqIndex, resIndex);
- finder.setCaseSensitive(caseSensitive.getState());
- finder.setIncludeDescription(searchDescription.getState());
- finder.setFindAll(findAll);
+ createFeatures.setEnabled(false);
+ FinderI finder = finders.get(av);
+ if (finder == null)
+ {
+ /*
+ * first time we searched this viewport
+ */
+ finder = new jalview.analysis.Finder(av);
+ finders.put(av, finder);
+ }
String searchString = textfield.getText();
-
- finder.find(searchString);
- seqIndex = finder.getSeqIndex();
- resIndex = finder.getResIndex();
- searchResults = finder.getSearchResults();
- Vector<SequenceI> idMatch = finder.getIdMatch();
- boolean haveResults = false;
- // set or reset the GUI
- if ((idMatch.size() > 0))
+ boolean isCaseSensitive = caseSensitive.getState();
+ boolean doSearchDescription = searchDescription.getState();
+ if (doFindAll)
{
- haveResults = true;
- ap.idPanel.highlightSearchResults(idMatch);
+ finder.findAll(searchString, isCaseSensitive, doSearchDescription);
}
else
{
- ap.idPanel.highlightSearchResults(null);
+ finder.findNext(searchString, isCaseSensitive, doSearchDescription);
}
- if (searchResults.getSize() > 0)
- {
- haveResults = true;
- createNewGroup.setEnabled(true);
+ searchResults = finder.getSearchResults();
+
+ List<SequenceI> idMatches = finder.getIdMatches();
+ ap.idPanel.highlightSearchResults(idMatches);
+ if (searchResults.isEmpty())
+ {
+ searchResults = null;
}
else
{
- searchResults = null;
+ createFeatures.setEnabled(true);
}
// if allResults is null, this effectively switches displaySearch flag in
ap.highlightSearchResults(searchResults);
// TODO: add enablers for 'SelectSequences' or 'SelectColumns' or
// 'SelectRegion' selection
- if (!haveResults)
+ if (idMatches.isEmpty() && searchResults == null)
{
ap.alignFrame.statusBar.setText(
MessageManager.getString("label.finished_searching"));
- resIndex = -1;
- seqIndex = 0;
}
else
{
- if (findAll)
+ if (doFindAll)
{
- String message = (idMatch.size() > 0) ? "" + idMatch.size() + " IDs"
+ String message = (idMatches.size() > 0) ? "" + idMatches.size() + " IDs"
: "";
- if (idMatch.size() > 0 && searchResults != null
+ if (idMatches.size() > 0 && searchResults != null
&& searchResults.getSize() > 0)
{
message += " and ";
}
}
- Label jLabel1 = new Label();
-
- protected TextField textfield = new TextField();
-
- protected Button findAll = new Button();
-
- protected Button findNext = new Button();
-
- Panel actionsPanel = new Panel();
-
- GridLayout gridLayout1 = new GridLayout();
-
- protected Button createNewGroup = new Button();
-
- Checkbox caseSensitive = new Checkbox();
-
- Checkbox searchDescription = new Checkbox();
-
private void jbInit() throws Exception
{
+ Label jLabel1 = new Label(MessageManager.getString("action.find"));
jLabel1.setFont(new java.awt.Font("Verdana", 0, 12));
- jLabel1.setText(MessageManager.getString("action.find"));
jLabel1.setBounds(new Rectangle(3, 30, 34, 15));
this.setLayout(null);
textfield.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
@Override
public void keyTyped(KeyEvent e)
{
- textfield_keyTyped(e);
+ textfield_keyTyped();
}
});
textfield.addActionListener(this);
findNext.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
findNext.setLabel(MessageManager.getString("action.find_next"));
findNext.addActionListener(this);
+
+ Panel actionsPanel = new Panel();
actionsPanel.setBounds(new Rectangle(195, 5, 141, 64));
+ GridLayout gridLayout1 = new GridLayout();
actionsPanel.setLayout(gridLayout1);
gridLayout1.setHgap(0);
gridLayout1.setRows(3);
gridLayout1.setVgap(2);
- createNewGroup.setEnabled(false);
- createNewGroup.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
- createNewGroup.setLabel(MessageManager.getString("label.new_feature"));
- createNewGroup.addActionListener(this);
+ createFeatures.setEnabled(false);
+ createFeatures.setFont(new java.awt.Font("Verdana", Font.PLAIN, 10));
+ createFeatures.setLabel(MessageManager.getString("label.new_feature"));
+ createFeatures.addActionListener(this);
caseSensitive.setLabel(MessageManager.getString("label.match_case"));
caseSensitive.setBounds(new Rectangle(30, 39, 126, 23));
searchDescription.setBounds(new Rectangle(30, 59, 170, 23));
actionsPanel.add(findNext, null);
actionsPanel.add(findAll, null);
- actionsPanel.add(createNewGroup, null);
+ actionsPanel.add(createFeatures, null);
this.add(caseSensitive);
this.add(textfield, null);
this.add(jLabel1, null);
this.add(searchDescription);
}
- void textfield_keyTyped(KeyEvent e)
+ void textfield_keyTyped()
{
findNext.setEnabled(true);
}
{
idCanvas.setHighlighted(list);
- if (list == null)
+ if (list == null || list.isEmpty())
{
return;
}
*/
int getEnd();
+ /**
+ * Answers true if this match is for the given sequence and includes (matches
+ * or encloses) the given start-end range
+ *
+ * @param seq
+ * @param start
+ * @param end
+ * @return
+ */
+ boolean contains(SequenceI seq, int start, int end);
}
\ No newline at end of file
}
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultMatchI#getSequence()
- */
@Override
public SequenceI getSequence()
{
return sequence;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultMatchI#getStart()
- */
@Override
public int getStart()
{
return start;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultMatchI#getEnd()
- */
@Override
public int getEnd()
{
return (sequence == m.getSequence() && start == m.getStart()
&& end == m.getEnd());
}
+
+ @Override
+ public boolean contains(SequenceI seq, int from, int to)
+ {
+ return (sequence == seq && start <= from && end >= to);
+ }
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultsI#addResult(jalview.datamodel.SequenceI, int, int)
- */
@Override
public SearchResultMatchI addResult(SequenceI seq, int start, int end)
{
Match m = new Match(seq, start, end);
- matches.add(m);
+ if (!matches.contains(m))
+ {
+ matches.add(m);
+ }
return m;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultsI#involvesSequence(jalview.datamodel.SequenceI)
- */
@Override
public boolean involvesSequence(SequenceI sequence)
{
return false;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultsI#getResults(jalview.datamodel.SequenceI, int, int)
- */
@Override
public int[] getResults(SequenceI sequence, int start, int end)
{
return count;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultsI#getSize()
- */
@Override
public int getSize()
{
return matches.size();
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultsI#isEmpty()
- */
@Override
public boolean isEmpty()
{
return matches.isEmpty();
}
- /* (non-Javadoc)
- * @see jalview.datamodel.SearchResultsI#getResults()
- */
@Override
public List<SearchResultMatchI> getResults()
{
{
/**
- * Adds one region to the results
+ * Adds one region to the results (unless already added, to avoid duplicates)
*
* @param seq
- * Sequence
* @param start
- * int
* @param end
- * int
* @return
*/
SearchResultMatchI addResult(SequenceI seq, int start, int end);
* get a range on the sequence as a string
*
* @param start
- * position relative to start of sequence including gaps (from 0)
+ * (inclusive) position relative to start of sequence including gaps
+ * (from 0)
* @param end
- * position relative to start of sequence including gaps (from 0)
+ * (exclusive) position relative to start of sequence including gaps
+ * (from 0)
*
* @return String containing all gap and symbols in specified range
*/
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
+import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
@SuppressWarnings("serial")
public abstract class GFTSPanel extends JPanel implements GFTSPanelI
{
+ private static final Font VERDANA_12 = new Font("Verdana", 0, 12);
+
protected JInternalFrame mainFrame = new JInternalFrame(
getFTSFrameTitle());
Integer height = getTempUserPrefs().get("FTSPanel.height") == null ? 400
: getTempUserPrefs().get("FTSPanel.height");
lbl_warning.setVisible(false);
- lbl_warning.setFont(new java.awt.Font("Verdana", 0, 12));
+ lbl_warning.setFont(VERDANA_12);
lbl_loading.setVisible(false);
- lbl_loading.setFont(new java.awt.Font("Verdana", 0, 12));
+ lbl_loading.setFont(VERDANA_12);
lbl_blank.setVisible(true);
- lbl_blank.setFont(new java.awt.Font("Verdana", 0, 12));
+ lbl_blank.setFont(VERDANA_12);
tbl_summary.setAutoCreateRowSorter(true);
tbl_summary.getTableHeader().setReorderingAllowed(false);
}
});
+ JButton txt_help = new JButton("?");
+ txt_help.setFont(VERDANA_12);
+ txt_help.setPreferredSize(new Dimension(15, 15));
+ txt_help.setToolTipText(MessageManager.getString("action.help"));
+ txt_help.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ showHelp();
+ }
+ });
+
btn_autosearch.setText(MessageManager.getString("option.autosearch"));
btn_autosearch.setToolTipText(
MessageManager.getString("option.enable_disable_autosearch"));
Boolean.toString(btn_autosearch.isSelected()));
}
});
- btn_back.setFont(new java.awt.Font("Verdana", 0, 12));
+ btn_back.setFont(VERDANA_12);
btn_back.setText(MessageManager.getString("action.back"));
btn_back.addActionListener(new java.awt.event.ActionListener()
{
});
btn_ok.setEnabled(false);
- btn_ok.setFont(new java.awt.Font("Verdana", 0, 12));
+ btn_ok.setFont(VERDANA_12);
btn_ok.setText(MessageManager.getString("action.ok"));
btn_ok.addActionListener(new java.awt.event.ActionListener()
{
btn_next_page.setEnabled(false);
btn_next_page.setToolTipText(
MessageManager.getString("label.next_page_tooltip"));
- btn_next_page.setFont(new java.awt.Font("Verdana", 0, 12));
+ btn_next_page.setFont(VERDANA_12);
btn_next_page.setText(MessageManager.getString("action.next_page"));
btn_next_page.addActionListener(new java.awt.event.ActionListener()
{
btn_prev_page.setEnabled(false);
btn_prev_page.setToolTipText(
MessageManager.getString("label.prev_page_tooltip"));
- btn_prev_page.setFont(new java.awt.Font("Verdana", 0, 12));
+ btn_prev_page.setFont(VERDANA_12);
btn_prev_page.setText(MessageManager.getString("action.prev_page"));
btn_prev_page.addActionListener(new java.awt.event.ActionListener()
{
btn_next_page.setVisible(false);
}
- btn_cancel.setFont(new java.awt.Font("Verdana", 0, 12));
+ btn_cancel.setFont(VERDANA_12);
btn_cancel.setText(MessageManager.getString("action.cancel"));
btn_cancel.addActionListener(new java.awt.event.ActionListener()
{
});
scrl_searchResult.setPreferredSize(new Dimension(width, height));
- cmb_searchTarget.setFont(new java.awt.Font("Verdana", 0, 12));
+ cmb_searchTarget.setFont(VERDANA_12);
cmb_searchTarget.addItemListener(new ItemListener()
{
@Override
}
});
- txt_search.setFont(new java.awt.Font("Verdana", 0, 12));
+ txt_search.setFont(VERDANA_12);
txt_search.getEditor().getEditorComponent()
.addKeyListener(new KeyAdapter()
pnl_results.add(tabbedPane);
pnl_inputs.add(cmb_searchTarget);
pnl_inputs.add(txt_search);
+ pnl_inputs.add(txt_help);
pnl_inputs.add(btn_autosearch);
pnl_inputs.add(lbl_loading);
pnl_inputs.add(lbl_warning);
Desktop.addInternalFrame(mainFrame, getFTSFrameTitle(), width, height);
}
+ abstract protected void showHelp();
+
protected void closeAction()
{
getTempUserPrefs().put("FTSPanel.width", this.getWidth());
import jalview.fts.core.FTSRestRequest;
import jalview.fts.core.FTSRestResponse;
import jalview.fts.core.GFTSPanel;
+import jalview.gui.Help;
+import jalview.gui.Help.HelpId;
import jalview.gui.SequenceFetcher;
import jalview.util.MessageManager;
import java.util.HashSet;
import java.util.Map;
+import javax.help.HelpSetException;
+
@SuppressWarnings("serial")
public class PDBFTSPanel extends GFTSPanel
{
private static String defaultFTSFrameTitle = MessageManager
.getString("label.pdb_sequence_fetcher");
- private static Map<String, Integer> tempUserPrefs = new HashMap<String, Integer>();
+ private static Map<String, Integer> tempUserPrefs = new HashMap<>();
private static final String PDB_FTS_CACHE_KEY = "CACHE.PDB_FTS";
// mainFrame.dispose();
disableActionButtons();
StringBuilder selectedIds = new StringBuilder();
- HashSet<String> selectedIdsSet = new HashSet<String>();
+ HashSet<String> selectedIdsSet = new HashSet<>();
int primaryKeyColIndex = 0;
try
{
{
return PDB_AUTOSEARCH;
}
+
+ @Override
+ protected void showHelp()
+ {
+ try
+ {
+ Help.showHelpWindow(HelpId.PdbFts);
+ } catch (HelpSetException e1)
+ {
+ e1.printStackTrace();
+ }
+ }
}
\ No newline at end of file
import jalview.fts.core.FTSRestRequest;
import jalview.fts.core.FTSRestResponse;
import jalview.fts.core.GFTSPanel;
+import jalview.gui.Help;
+import jalview.gui.Help.HelpId;
import jalview.gui.SequenceFetcher;
import jalview.util.MessageManager;
import java.util.HashSet;
import java.util.Map;
+import javax.help.HelpSetException;
+
@SuppressWarnings("serial")
public class UniprotFTSPanel extends GFTSPanel
{
{
return UNIPROT_AUTOSEARCH;
}
+
+ @Override
+ protected void showHelp()
+ {
+ try
+ {
+ Help.showHelpWindow(HelpId.UniprotFts);
+ } catch (HelpSetException e1)
+ {
+ e1.printStackTrace();
+ }
+ }
}
}
}
});
- help.setFont(JvSwingUtils.getLabelFont());
- help.setText(MessageManager.getString("action.help"));
- help.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- try
- {
- Help.showHelpWindow(HelpId.SequenceFeatureSettings);
- } catch (HelpSetException e1)
- {
- e1.printStackTrace();
- }
- }
- });
JButton cancel = new JButton(MessageManager.getString("action.cancel"));
cancel.setFont(JvSwingUtils.getLabelFont());
*/
package jalview.gui;
+import jalview.api.AlignViewportI;
+import jalview.api.FinderI;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceFeature;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
-import java.util.Vector;
+import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
import javax.swing.KeyStroke;
+import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
/**
*/
public class Finder extends GFinder
{
- private static final int MY_HEIGHT = 120;
+ private static final int MIN_WIDTH = 350;
- private static final int MY_WIDTH = 400;
+ private static final int MIN_HEIGHT = 120;
- AlignmentViewport av;
+ private static final int MY_HEIGHT = 120;
- AlignmentPanel ap;
+ private static final int MY_WIDTH = 400;
- private static final int MIN_WIDTH = 350;
+ private AlignViewportI av;
- private static final int MIN_HEIGHT = 120;
+ private AlignmentPanel ap;
- JInternalFrame frame;
+ private JInternalFrame frame;
- int seqIndex = 0;
+ /*
+ * Finder agent per viewport searched
+ */
+ private Map<AlignViewportI, FinderI> finders;
- int resIndex = -1;
+ private SearchResultsI searchResults;
- SearchResultsI searchResults;
+ /*
+ * true if we only search a given alignment view
+ */
+ private boolean focusfixed;
/**
- * Creates a new Finder object with no associated viewport or panel.
+ * Creates a new Finder object with no associated viewport or panel. Each Find
+ * or Find Next action will act on whichever viewport has focus at the time.
*/
public Finder()
{
this(null, null);
- focusfixed = false;
}
/**
{
av = viewport;
ap = alignPanel;
- focusfixed = true;
+ finders = new HashMap<>();
+ focusfixed = viewport != null;
frame = new JInternalFrame();
frame.setContentPane(this);
frame.setLayer(JLayeredPane.PALETTE_LAYER);
frame.addInternalFrameListener(
- new javax.swing.event.InternalFrameAdapter()
+ new InternalFrameAdapter()
{
@Override
public void internalFrameClosing(InternalFrameEvent e)
}
/**
- * Performs the 'Find Next' action.
- *
- * @param e
+ * Performs the 'Find Next' action on the alignment panel with focus
*/
@Override
- public void findNext_actionPerformed(ActionEvent e)
+ public void findNext_actionPerformed()
{
if (getFocusedViewport())
{
}
/**
- * Performs the 'Find All' action.
- *
- * @param e
+ * Performs the 'Find All' action on the alignment panel with focus
*/
@Override
- public void findAll_actionPerformed(ActionEvent e)
+ public void findAll_actionPerformed()
{
if (getFocusedViewport())
{
- resIndex = -1;
- seqIndex = 0;
doSearch(true);
}
}
/**
- * do we only search a given alignment view ?
- */
- private boolean focusfixed;
-
- /**
* if !focusfixed and not in a desktop environment, checks that av and ap are
* valid. Otherwise, gets the topmost alignment window and sets av and ap
* accordingly
for (int f = 0; f < frames.length; f++)
{
JInternalFrame alignFrame = frames[f];
- if (alignFrame != null && alignFrame instanceof AlignFrame)
+ if (alignFrame != null && alignFrame instanceof AlignFrame
+ && !alignFrame.isIcon())
{
av = ((AlignFrame) alignFrame).viewport;
ap = ((AlignFrame) alignFrame).alignPanel;
@Override
public void createFeatures_actionPerformed()
{
- List<SequenceI> seqs = new ArrayList<SequenceI>();
- List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+ List<SequenceI> seqs = new ArrayList<>();
+ List<SequenceFeature> features = new ArrayList<>();
String searchString = searchBox.getEditor().getItem().toString().trim();
String desc = "Search Results";
// other stuff
// TODO: add switches to control what is searched - sequences, IDS,
// descriptions, features
- jalview.analysis.Finder finder = new jalview.analysis.Finder(
- av.getAlignment(), av.getSelectionGroup(), seqIndex, resIndex);
- finder.setCaseSensitive(caseSensitive.isSelected());
- finder.setIncludeDescription(searchDescription.isSelected());
-
- finder.setFindAll(doFindAll);
-
- finder.find(searchString); // returns true if anything was actually found
-
- seqIndex = finder.getSeqIndex();
- resIndex = finder.getResIndex();
+ FinderI finder = finders.get(av);
+ if (finder == null)
+ {
+ /*
+ * first time we've searched this viewport
+ */
+ finder = new jalview.analysis.Finder(av);
+ finders.put(av, finder);
+ }
- searchResults = finder.getSearchResults(); // find(regex,
- // caseSensitive.isSelected(), )
- Vector<SequenceI> idMatch = finder.getIdMatch();
- boolean haveResults = false;
- // set or reset the GUI
- if ((idMatch.size() > 0))
+ boolean isCaseSensitive = caseSensitive.isSelected();
+ boolean doSearchDescription = searchDescription.isSelected();
+ if (doFindAll)
{
- haveResults = true;
- ap.getIdPanel().highlightSearchResults(idMatch);
+ finder.findAll(searchString, isCaseSensitive, doSearchDescription);
}
else
{
- ap.getIdPanel().highlightSearchResults(null);
+ finder.findNext(searchString, isCaseSensitive, doSearchDescription);
}
- if (searchResults.getSize() > 0)
+ searchResults = finder.getSearchResults();
+ List<SequenceI> idMatch = finder.getIdMatches();
+ ap.getIdPanel().highlightSearchResults(idMatch);
+
+ if (searchResults.isEmpty())
{
- haveResults = true;
- createFeatures.setEnabled(true);
+ searchResults = null;
}
else
{
- searchResults = null;
+ createFeatures.setEnabled(true);
}
- // if allResults is null, this effectively switches displaySearch flag in
- // seqCanvas
ap.highlightSearchResults(searchResults);
// TODO: add enablers for 'SelectSequences' or 'SelectColumns' or
// 'SelectRegion' selection
- if (!haveResults)
+ if (idMatch.isEmpty() && searchResults == null)
{
JvOptionPane.showInternalMessageDialog(this,
MessageManager.getString("label.finished_searching"), null,
JvOptionPane.INFORMATION_MESSAGE);
- resIndex = -1;
- seqIndex = 0;
}
else
{
}
JvOptionPane.showInternalMessageDialog(this, message, null,
JvOptionPane.INFORMATION_MESSAGE);
- resIndex = -1;
- seqIndex = 0;
}
}
searchBox.updateCache();
*/
package jalview.gui;
+import java.awt.Point;
import java.net.URL;
import javax.help.BadIDException;
import javax.help.HelpSetException;
/**
- * Utility class to show the help documentation window.
+ * Utility class to show the help documentation window
*
* @author gmcarstairs
- *
*/
public class Help
{
public enum HelpId
{
Home("home"), SequenceFeatureSettings("seqfeatures.settings"),
- StructureViewer("viewingpdbs");
+ StructureViewer("viewingpdbs"), PdbFts("pdbfts"),
+ UniprotFts("uniprotfts");
private String id;
}
}
- private static final long HALF_A_MO = 500; // half a second
-
- private static long lastOpenedTime = 0L;
+ private static HelpBroker hb;
/**
* Not instantiable
}
/**
- * Show help text in a new window. But do nothing if within half a second of
- * the last invocation.
- *
- * This is a workaround for issue JAL-914 - both Desktop and AlignFrame
- * responding to F1 key, resulting in duplicate help windows opened.
+ * Shows the help window, at the entry specified by the given helpId
*
* @param id
- * TODO
*
* @throws HelpSetException
*/
public static void showHelpWindow(HelpId id) throws HelpSetException
{
- long timeNow = System.currentTimeMillis();
+ ClassLoader cl = Desktop.class.getClassLoader();
+ URL url = HelpSet.findHelpSet(cl, "help/help"); // $NON-NLS-$
+ HelpSet hs = new HelpSet(cl, url);
- if (timeNow - lastOpenedTime > HALF_A_MO)
+ if (hb == null)
{
- lastOpenedTime = timeNow;
- ClassLoader cl = Desktop.class.getClassLoader();
- URL url = HelpSet.findHelpSet(cl, "help/help"); // $NON-NLS-$
- HelpSet hs = new HelpSet(cl, url);
+ /*
+ * create help broker first time (only)
+ */
+ hb = hs.createHelpBroker();
+ }
- HelpBroker hb = hs.createHelpBroker();
- try
- {
- hb.setCurrentID(id.toString());
- } catch (BadIDException bad)
- {
- System.out.println("Bad help link: " + id.toString()
- + ": must match a target in help.jhm");
- throw bad;
- }
- hb.setDisplayed(true);
+ try
+ {
+ hb.setCurrentID(id.toString());
+ } catch (BadIDException bad)
+ {
+ System.out.println("Bad help link: " + id.toString()
+ + ": must match a target in help.jhm");
+ throw bad;
}
+
+ /*
+ * set Help visible - at its current location if it is already shown,
+ * else at a location as determined by the window manager
+ */
+ Point p = hb.getLocation();
+ hb.setLocation(p);
+ hb.setDisplayed(true);
}
+ /**
+ * Show the Help window at the root entry
+ *
+ * @throws HelpSetException
+ */
public static void showHelpWindow() throws HelpSetException
{
showHelpWindow(HelpId.Home);
{
getIdCanvas().setHighlighted(list);
- if (list == null)
+ if (list == null || list.isEmpty())
{
return;
}
}
ViewportRanges vpRanges = av.getRanges();
- int range = vpRanges.getEndRes() - vpRanges.getStartRes();
+ int range = vpRanges.getEndRes() - vpRanges.getStartRes() + 1;
if (scrollX > range)
{
scrollX = range;
{
ViewportRanges ranges = av.getRanges();
- if (Math.abs(scrollX) > ranges.getViewportWidth())
+ if (Math.abs(scrollX) >= ranges.getViewportWidth())
{
/*
- * shift of more than one view width is
+ * shift of one view width or more is
* overcomplicated to handle in this method
*/
fastPaint = false;
while (y >= 0)
{
+ /*
+ * shift 'widthToCopy' residues by 'positions' places to the right
+ */
gg.copyArea(copyFromLeftStart, y, widthToCopy, heightToCopy,
positions * charWidth, 0);
if (y > 0)
{
+ /*
+ * copy 'positions' residue from the row above (right hand end)
+ * to this row's left hand end
+ */
gg.copyArea(copyFromRightStart, y - wrappedRepeatHeightPx,
positions * charWidth, heightToCopy, -widthToCopy,
wrappedRepeatHeightPx);
public class GFinder extends JPanel
{
- JLabel jLabelFind = new JLabel();
+ private static final java.awt.Font VERDANA_12 = new java.awt.Font("Verdana", 0,
+ 12);
- protected JButton findAll = new JButton();
-
- protected JButton findNext = new JButton();
-
- JPanel actionsPanel = new JPanel();
-
- GridLayout gridLayout1 = new GridLayout();
+ private static final String FINDER_CACHE_KEY = "CACHE.FINDER";
protected JButton createFeatures = new JButton();
- protected JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<String>(
+ protected JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<>(
getCacheKey());
- BorderLayout mainBorderLayout = new BorderLayout();
-
- JPanel jPanel2 = new JPanel();
-
- JPanel jPanel3 = new JPanel();
-
- JPanel jPanel4 = new JPanel();
-
- BorderLayout borderLayout2 = new BorderLayout();
-
- JPanel jPanel6 = new JPanel();
-
protected JCheckBox caseSensitive = new JCheckBox();
protected JCheckBox searchDescription = new JCheckBox();
- GridLayout optionsGridLayout = new GridLayout();
-
- private static final String FINDER_CACHE_KEY = "CACHE.FINDER";
-
public GFinder()
{
try
private void jbInit() throws Exception
{
- jLabelFind.setFont(new java.awt.Font("Verdana", 0, 12));
- jLabelFind.setText(MessageManager.getString("label.find"));
+ BorderLayout mainBorderLayout = new BorderLayout();
this.setLayout(mainBorderLayout);
- findAll.setFont(new java.awt.Font("Verdana", 0, 12));
- findAll.setText(MessageManager.getString("action.find_all"));
+ mainBorderLayout.setHgap(5);
+ mainBorderLayout.setVgap(5);
+
+ JLabel jLabelFind = new JLabel(MessageManager.getString("label.find"));
+ jLabelFind.setFont(VERDANA_12);
+
+ JButton findAll = new JButton(
+ MessageManager.getString("action.find_all"));
+ findAll.setFont(VERDANA_12);
findAll.addActionListener(new java.awt.event.ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- findAll_actionPerformed(e);
+ findAll_actionPerformed();
}
});
- findNext.setFont(new java.awt.Font("Verdana", 0, 12));
- findNext.setText(MessageManager.getString("action.find_next"));
+
+ JButton findNext = new JButton(
+ MessageManager.getString("action.find_next"));
+ findNext.setFont(VERDANA_12);
findNext.addActionListener(new java.awt.event.ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- findNext_actionPerformed(e);
+ findNext_actionPerformed();
}
});
+
+ JPanel actionsPanel = new JPanel();
+ GridLayout gridLayout1 = new GridLayout();
actionsPanel.setLayout(gridLayout1);
gridLayout1.setHgap(0);
gridLayout1.setRows(3);
gridLayout1.setVgap(2);
+
createFeatures.setEnabled(false);
- createFeatures.setFont(new java.awt.Font("Verdana", 0, 12));
+ createFeatures.setFont(VERDANA_12);
createFeatures.setMargin(new Insets(0, 0, 0, 0));
createFeatures.setText(MessageManager.getString("label.new_feature"));
createFeatures.addActionListener(new java.awt.event.ActionListener()
@Override
public void caretUpdate(CaretEvent e)
{
- textfield_caretUpdate(e);
+ textfield_caretUpdate();
}
});
searchBox.getEditor().getEditorComponent()
textfield_keyPressed(e);
}
});
- mainBorderLayout.setHgap(5);
- mainBorderLayout.setVgap(5);
- jPanel4.setLayout(borderLayout2);
- jPanel2.setPreferredSize(new Dimension(10, 1));
- jPanel3.setPreferredSize(new Dimension(10, 1));
+
caseSensitive.setHorizontalAlignment(SwingConstants.LEFT);
caseSensitive.setText(MessageManager.getString("label.match_case"));
actionsPanel.add(createFeatures, null);
this.add(jLabelFind, java.awt.BorderLayout.WEST);
this.add(actionsPanel, java.awt.BorderLayout.EAST);
+
+ JPanel jPanel2 = new JPanel();
+ jPanel2.setPreferredSize(new Dimension(10, 1));
+ JPanel jPanel3 = new JPanel();
+ jPanel3.setPreferredSize(new Dimension(10, 1));
+ JPanel jPanel4 = new JPanel();
+ jPanel4.setLayout(new BorderLayout());
this.add(jPanel2, java.awt.BorderLayout.SOUTH);
this.add(jPanel3, java.awt.BorderLayout.NORTH);
this.add(jPanel4, java.awt.BorderLayout.CENTER);
JPanel optionsPanel = new JPanel();
+ GridLayout optionsGridLayout = new GridLayout();
optionsGridLayout.setHgap(0);
optionsGridLayout.setRows(2);
optionsGridLayout.setVgap(2);
if (!searchBox.isPopupVisible())
{
e.consume();
- findNext_actionPerformed(null);
+ findNext_actionPerformed();
}
}
}
- protected void findNext_actionPerformed(ActionEvent e)
+ protected void findNext_actionPerformed()
{
}
- protected void findAll_actionPerformed(ActionEvent e)
+ protected void findAll_actionPerformed()
{
}
{
}
- public void textfield_caretUpdate(CaretEvent e)
+ public void textfield_caretUpdate()
{
- if (searchBox.getUserInput().indexOf(">") > -1)
+ // disabled as appears to be running a non-functional
+ if (false && searchBox.getUserInput().indexOf(">") > -1)
{
SwingUtilities.invokeLater(new Runnable()
{
str = jalview.analysis.AlignSeq.extractGaps(
jalview.util.Comparison.GapChars,
al.getSequenceAt(0).getSequenceAsString());
-
+ // todo and what? set str as searchBox text?
}
}
});
assertEquals(AlignSeq.extractGaps(" -", " AC-G.T"), "ACG.T");
assertEquals(AlignSeq.extractGaps(" -.", " AC-G.T ."), "ACGT");
assertEquals(AlignSeq.extractGaps("-", " AC-G.T"), " ACG.T");
+ assertEquals(AlignSeq.extractGaps("-. ", " -. .-"), "");
}
@Test(groups = { "Functional" })
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
+import jalview.api.AlignViewportI;
+import jalview.api.FinderI;
+import jalview.bin.Cache;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceGroup;
import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
import jalview.gui.JvOptionPane;
import jalview.io.DataSourceType;
import jalview.io.FileLoader;
import java.util.List;
+import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import junit.extensions.PA;
+
public class FinderTest
{
@BeforeClass(alwaysRun = true)
private AlignmentI al;
+ private AlignViewportI av;
+
@BeforeClass(groups = "Functional")
public void setUp()
{
- String seqData = "seq1 ABCD--EF-GHI\n" + "seq2 A--BCDefHI\n"
+ Cache.loadProperties("test/jalview/io/testProps.jvprops");
+ Cache.applicationProperties.setProperty("PAD_GAPS",
+ Boolean.FALSE.toString());
+
+ String seqData = "seq1seq1/8-18 ABCD--EF-GHIJI\n" + "seq2 A--BCDefHI\n"
+ "seq3 --bcdEFH\n" + "seq4 aa---aMMMMMaaa\n";
af = new FileLoader().LoadFileWaitTillLoaded(seqData,
DataSourceType.PASTE);
- al = af.getViewport().getAlignment();
+ av = af.getViewport();
+ al = av.getAlignment();
+ }
+
+ @AfterMethod
+ public void tearDownAfterTest()
+ {
+ av.setSelectionGroup(null);
}
/**
- * Test for find all matches of a regular expression
+ * Test for find matches of a regular expression
*/
@Test(groups = "Functional")
- public void testFindAll_regex()
+ public void testFind_regex()
{
- Finder f = new Finder(al, null);
- f.setFindAll(true);
- f.find("E.H"); // 'E, any character, H'
+ /*
+ * find next match only
+ */
+ Finder f = new Finder(av);
+ f.findNext("E.H", false, false); // 'E, any character, H'
+ // should match seq2 efH only
+ SearchResultsI sr = f.getSearchResults();
+ assertEquals(sr.getSize(), 1);
+ List<SearchResultMatchI> matches = sr.getResults();
+ assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
+ assertEquals(matches.get(0).getStart(), 5);
+ assertEquals(matches.get(0).getEnd(), 7);
+ f = new Finder(av);
+ f.findAll("E.H", false, false); // 'E, any character, H'
// should match seq2 efH and seq3 EFH
- SearchResultsI sr = f.getSearchResults();
+ sr = f.getSearchResults();
assertEquals(sr.getSize(), 2);
- List<SearchResultMatchI> matches = sr.getResults();
- assertSame(al.getSequenceAt(1), matches.get(0).getSequence());
- assertSame(al.getSequenceAt(2), matches.get(1).getSequence());
+ matches = sr.getResults();
+ assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
+ assertSame(matches.get(1).getSequence(), al.getSequenceAt(2));
assertEquals(matches.get(0).getStart(), 5);
assertEquals(matches.get(0).getEnd(), 7);
assertEquals(matches.get(1).getStart(), 4);
@Test(groups = "Functional")
public void testFind_residueNumber()
{
- Finder f = new Finder(al, null);
- f.setFindAll(true);
- f.find("9");
+ Finder f = new Finder(av);
- // seq1 and seq4 have 9 residues; no match in other sequences
+ /*
+ * find first match should return seq1 residue 9
+ */
+ f.findNext("9", false, false);
SearchResultsI sr = f.getSearchResults();
- assertEquals(sr.getSize(), 2);
+ assertEquals(sr.getSize(), 1);
List<SearchResultMatchI> matches = sr.getResults();
- assertSame(al.getSequenceAt(0), matches.get(0).getSequence());
- assertSame(al.getSequenceAt(3), matches.get(1).getSequence());
+ assertSame(matches.get(0).getSequence(), al.getSequenceAt(0));
+ assertEquals(matches.get(0).getStart(), 9);
+ assertEquals(matches.get(0).getEnd(), 9);
+
+ /*
+ * find all matches should return seq1 and seq4 (others are too short)
+ */
+ f = new Finder(av);
+ f.findAll("9", false, false);
+ sr = f.getSearchResults();
+ assertEquals(sr.getSize(), 2);
+ matches = sr.getResults();
+ assertSame(matches.get(0).getSequence(), al.getSequenceAt(0));
+ assertSame(matches.get(1).getSequence(), al.getSequenceAt(3));
assertEquals(matches.get(0).getStart(), 9);
assertEquals(matches.get(0).getEnd(), 9);
assertEquals(matches.get(1).getStart(), 9);
assertEquals(matches.get(1).getEnd(), 9);
+
+ /*
+ * parsing of search string as integer is strict
+ */
+ f = new Finder(av);
+ f.findNext(" 9", false, false);
+ assertTrue(f.getSearchResults().isEmpty());
}
/**
public void testFindNext()
{
/*
- * start at second sequence; resIndex of -1
+ * start at second sequence; colIndex of -1
* means sequence id / description is searched
*/
- Finder f = new Finder(al, null, 1, -1);
- f.find("e"); // matches id
+ Finder f = new Finder(av);
+ PA.setValue(f, "sequenceIndex", 1);
+ PA.setValue(f, "columnIndex", -1);
+ f.findNext("e", false, false); // matches id
assertTrue(f.getSearchResults().isEmpty());
- assertEquals(f.getIdMatch().size(), 1);
- assertSame(f.getIdMatch().get(0), al.getSequenceAt(1));
-
- // resIndex is now 0 - for use in next find next
- assertEquals(f.getResIndex(), 0);
- f = new Finder(al, null, 1, 0);
- f.find("e"); // matches in sequence
- assertTrue(f.getIdMatch().isEmpty());
+ assertEquals(f.getIdMatches().size(), 1);
+ assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
+
+ // colIndex is now 0 - for use in next find next
+ // searching A--BCDefHI
+ assertEquals(PA.getValue(f, "columnIndex"), 0);
+ f = new Finder(av);
+ PA.setValue(f, "sequenceIndex", 1);
+ PA.setValue(f, "columnIndex", 0);
+ f.findNext("e", false, false); // matches in sequence
+ assertTrue(f.getIdMatches().isEmpty());
assertEquals(f.getSearchResults().getSize(), 1);
List<SearchResultMatchI> matches = f.getSearchResults().getResults();
assertEquals(matches.get(0).getStart(), 5);
assertEquals(matches.get(0).getEnd(), 5);
assertSame(matches.get(0).getSequence(), al.getSequenceAt(1));
// still in the second sequence
- assertEquals(f.getSeqIndex(), 1);
- // next residue position to search from is 5
- // (used as base 0 by RegEx so the same as 6 if base 1)
- assertEquals(f.getResIndex(), 5);
+ assertEquals(PA.getValue(f, "sequenceIndex"), 1);
+ // next column position to search from is 7
+ assertEquals(PA.getValue(f, "columnIndex"), 7);
// find next from end of sequence - finds next sequence id
- f = new Finder(al, null, 1, 5);
- f.find("e");
- assertEquals(f.getIdMatch().size(), 1);
- assertSame(f.getIdMatch().get(0), al.getSequenceAt(2));
+ f = new Finder(av);
+ PA.setValue(f, "sequenceIndex", 1);
+ PA.setValue(f, "columnIndex", 7);
+ f.findNext("e", false, false);
+ assertEquals(f.getIdMatches().size(), 1);
+ assertSame(f.getIdMatches().get(0), al.getSequenceAt(2));
+ assertTrue(f.getSearchResults().isEmpty());
}
/**
* Test for matching within sequence descriptions
*/
@Test(groups = "Functional")
- public void testFindAll_inDescription()
+ public void testFind_inDescription()
{
AlignmentI al2 = new Alignment(al);
al2.getSequenceAt(0).setDescription("BRAF");
al2.getSequenceAt(1).setDescription("braf");
- Finder f = new Finder(al2, null);
- f.setFindAll(true);
- f.setIncludeDescription(true);
-
- f.find("rAF");
- assertEquals(f.getIdMatch().size(), 2);
- assertSame(f.getIdMatch().get(0), al2.getSequenceAt(0));
- assertSame(f.getIdMatch().get(1), al2.getSequenceAt(1));
+
+ AlignViewportI av2 = new AlignViewport(al2);
+
+ /*
+ * find first match only
+ */
+ Finder f = new Finder(av2);
+ f.findNext("rAF", false, true);
+ assertEquals(f.getIdMatches().size(), 1);
+ assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
assertTrue(f.getSearchResults().isEmpty());
/*
- * case sensitive
+ * find all matches
*/
- f = new Finder(al2, null);
- f.setFindAll(true);
- f.setCaseSensitive(true);
- f.setIncludeDescription(true);
+ f = new Finder(av2);
+ f.findAll("rAF", false, true);
+ assertEquals(f.getIdMatches().size(), 2);
+ assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
+ assertSame(f.getIdMatches().get(1), al2.getSequenceAt(1));
+ assertTrue(f.getSearchResults().isEmpty());
- f.find("RAF");
- assertEquals(f.getIdMatch().size(), 1);
- assertSame(f.getIdMatch().get(0), al2.getSequenceAt(0));
+ /*
+ * case sensitive
+ */
+ f = new Finder(av2);
+ f.findAll("RAF", true, true);
+ assertEquals(f.getIdMatches().size(), 1);
+ assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
assertTrue(f.getSearchResults().isEmpty());
/*
al2.getSequenceAt(0).setDescription("the efh sequence");
al2.getSequenceAt(0).setName("mouseEFHkinase");
al2.getSequenceAt(1).setName("humanEFHkinase");
- f = new Finder(al2, null);
- f.setFindAll(true);
- f.setIncludeDescription(true);
+ f = new Finder(av2);
/*
* sequence matches should have no duplicates
*/
- f.find("EFH");
- assertEquals(f.getIdMatch().size(), 2);
- assertSame(f.getIdMatch().get(0), al2.getSequenceAt(0));
- assertSame(f.getIdMatch().get(1), al2.getSequenceAt(1));
+ f.findAll("EFH", false, true);
+ assertEquals(f.getIdMatches().size(), 2);
+ assertSame(f.getIdMatches().get(0), al2.getSequenceAt(0));
+ assertSame(f.getIdMatches().get(1), al2.getSequenceAt(1));
assertEquals(f.getSearchResults().getSize(), 2);
SearchResultMatchI match = f.getSearchResults().getResults().get(0);
- assertSame(al2.getSequenceAt(1), match.getSequence());
- assertEquals(5, match.getStart());
- assertEquals(7, match.getEnd());
+ assertSame(match.getSequence(), al2.getSequenceAt(1));
+ assertEquals(match.getStart(), 5);
+ assertEquals(match.getEnd(), 7);
match = f.getSearchResults().getResults().get(1);
- assertSame(al2.getSequenceAt(2), match.getSequence());
- assertEquals(4, match.getStart());
- assertEquals(6, match.getEnd());
+ assertSame(match.getSequence(), al2.getSequenceAt(2));
+ assertEquals(match.getStart(), 4);
+ assertEquals(match.getEnd(), 6);
}
/**
@Test(groups = "Functional")
public void testFindAll_sequenceIds()
{
- Finder f = new Finder(al, null);
- f.setFindAll(true);
+ Finder f = new Finder(av);
/*
- * case insensitive
+ * case insensitive; seq1 occurs twice in sequence id but
+ * only one match should be returned
*/
- f.find("SEQ1");
- assertEquals(f.getIdMatch().size(), 1);
- assertSame(f.getIdMatch().get(0), al.getSequenceAt(0));
- assertTrue(f.getSearchResults().isEmpty());
+ f.findAll("SEQ1", false, false);
+ assertEquals(f.getIdMatches().size(), 1);
+ assertSame(f.getIdMatches().get(0), al.getSequenceAt(0));
+ SearchResultsI searchResults = f.getSearchResults();
+ assertTrue(searchResults.isEmpty());
/*
* case sensitive
*/
- f = new Finder(al, null);
- f.setFindAll(true);
- f.setCaseSensitive(true);
- f.find("SEQ1");
- assertTrue(f.getSearchResults().isEmpty());
+ f = new Finder(av);
+ f.findAll("SEQ1", true, false);
+ searchResults = f.getSearchResults();
+ assertTrue(searchResults.isEmpty());
/*
* match both sequence id and sequence
*/
AlignmentI al2 = new Alignment(al);
+ AlignViewportI av2 = new AlignViewport(al2);
al2.addSequence(new Sequence("aBz", "xyzabZpqrAbZ"));
- f = new Finder(al2, null);
- f.setFindAll(true);
- f.find("ABZ");
- assertEquals(f.getIdMatch().size(), 1);
- assertSame(f.getIdMatch().get(0), al2.getSequenceAt(4));
- assertEquals(f.getSearchResults().getSize(), 2);
- SearchResultMatchI match = f.getSearchResults().getResults().get(0);
- assertSame(al2.getSequenceAt(4), match.getSequence());
- assertEquals(4, match.getStart());
- assertEquals(6, match.getEnd());
- match = f.getSearchResults().getResults().get(1);
- assertSame(al2.getSequenceAt(4), match.getSequence());
- assertEquals(10, match.getStart());
- assertEquals(12, match.getEnd());
+ f = new Finder(av2);
+ f.findAll("ABZ", false, false);
+ assertEquals(f.getIdMatches().size(), 1);
+ assertSame(f.getIdMatches().get(0), al2.getSequenceAt(4));
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 2);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al2.getSequenceAt(4));
+ assertEquals(match.getStart(), 4);
+ assertEquals(match.getEnd(), 6);
+ match = searchResults.getResults().get(1);
+ assertSame(match.getSequence(), al2.getSequenceAt(4));
+ assertEquals(match.getStart(), 10);
+ assertEquals(match.getEnd(), 12);
}
/**
- * Test finding all matches of a sequence pattern in an alignment
+ * Test finding next match of a sequence pattern in an alignment
*/
@Test(groups = "Functional")
- public void testFindAll_simpleMatch()
+ public void testFind_findNext()
{
- Finder f = new Finder(al, null);
- f.setFindAll(true);
+ /*
+ * efh should be matched in seq2 only
+ */
+ FinderI f = new Finder(av);
+ f.findNext("EfH", false, false);
+ SearchResultsI searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 5);
+ assertEquals(match.getEnd(), 7);
/*
- * case insensitive first
+ * I should be found in seq1 (twice) and seq2 (once)
*/
- f.find("EfH");
+ f = new Finder(av);
+ f.findNext("I", false, false); // find next: seq1/16
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(0));
+ assertEquals(match.getStart(), 16);
+ assertEquals(match.getEnd(), 16);
+
+ f.findNext("I", false, false); // find next: seq1/18
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(0));
+ assertEquals(match.getStart(), 18);
+ assertEquals(match.getEnd(), 18);
+
+ f.findNext("I", false, false); // find next: seq2/8
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 8);
+ assertEquals(match.getEnd(), 8);
+
+ f.findNext("I", false, false);
+ assertTrue(f.getSearchResults().isEmpty());
+
+ /*
+ * find should reset to start of alignment after a failed search
+ */
+ f.findNext("I", false, false); // find next: seq1/16
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(0));
+ assertEquals(match.getStart(), 16);
+ assertEquals(match.getEnd(), 16);
+ }
+
+ /**
+ * Test for JAL-2302 to verify that sub-matches are not included in a find all
+ * result
+ */
+ @Test(groups = "Functional")
+ public void testFind_maximalResultOnly()
+ {
+ Finder f = new Finder(av);
+ f.findAll("M+", false, false);
+ SearchResultsI searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(3));
+ assertEquals(match.getStart(), 4); // dataset sequence positions
+ assertEquals(match.getEnd(), 8); // base 1
+ }
+
+ /**
+ * Test finding all matches of a sequence pattern in an alignment
+ */
+ @Test(groups = "Functional")
+ public void testFind_findAll()
+ {
+ Finder f = new Finder(av);
+ f.findAll("EfH", false, false);
SearchResultsI searchResults = f.getSearchResults();
assertEquals(searchResults.getSize(), 2);
SearchResultMatchI match = searchResults.getResults().get(0);
- assertSame(al.getSequenceAt(1), match.getSequence());
- assertEquals(5, match.getStart());
- assertEquals(7, match.getEnd());
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 5);
+ assertEquals(match.getEnd(), 7);
match = searchResults.getResults().get(1);
- assertSame(al.getSequenceAt(2), match.getSequence());
- assertEquals(4, match.getStart());
- assertEquals(6, match.getEnd());
+ assertSame(match.getSequence(), al.getSequenceAt(2));
+ assertEquals(match.getStart(), 4);
+ assertEquals(match.getEnd(), 6);
/*
- * case sensitive
+ * find all I should find 2 positions in seq1, 1 in seq2
*/
- f = new Finder(al, null);
- f.setFindAll(true);
- f.setCaseSensitive(true);
- f.find("BC");
+ f.findAll("I", false, false);
searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 3);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(0));
+ assertEquals(match.getStart(), 16);
+ assertEquals(match.getEnd(), 16);
+ match = searchResults.getResults().get(1);
+ assertSame(match.getSequence(), al.getSequenceAt(0));
+ assertEquals(match.getStart(), 18);
+ assertEquals(match.getEnd(), 18);
+ match = searchResults.getResults().get(2);
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 8);
+ assertEquals(match.getEnd(), 8);
+ }
+
+ /**
+ * Test finding all matches, case-sensitive
+ */
+ @Test(groups = "Functional")
+ public void testFind_findAllCaseSensitive()
+ {
+ Finder f = new Finder(av);
+
+ /*
+ * BC should match seq1/9-10 and seq2/2-3
+ */
+ f.findAll("BC", true, false);
+ SearchResultsI searchResults = f.getSearchResults();
assertEquals(searchResults.getSize(), 2);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(0));
+ assertEquals(match.getStart(), 9);
+ assertEquals(match.getEnd(), 10);
+ match = searchResults.getResults().get(1);
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 2);
+ assertEquals(match.getEnd(), 3);
+
+ /*
+ * bc should match seq3/1-2
+ */
+ f = new Finder(av);
+ f.findAll("bc", true, false);
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(2));
+ assertEquals(match.getStart(), 1);
+ assertEquals(match.getEnd(), 2);
+
+ f.findAll("bC", true, false);
+ assertTrue(f.getSearchResults().isEmpty());
+ }
+
+ /**
+ * Test finding next match of a sequence pattern in a selection group
+ */
+ @Test(groups = "Functional")
+ public void testFind_inSelection()
+ {
+ /*
+ * select sequences 2 and 3, columns 4-6 which contains
+ * BCD
+ * cdE
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(3);
+ sg.setEndRes(5);
+ sg.addSequence(al.getSequenceAt(1), false);
+ sg.addSequence(al.getSequenceAt(2), false);
+ av.setSelectionGroup(sg);
+
+ FinderI f = new Finder(av);
+ f.findNext("b", false, false);
+ assertTrue(f.getIdMatches().isEmpty());
+ SearchResultsI searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 2);
+ assertEquals(match.getEnd(), 2);
+
+ /*
+ * a second Find should not return the 'b' in seq3 as outside the selection
+ */
+ f.findNext("b", false, false);
+ assertTrue(f.getSearchResults().isEmpty());
+ assertTrue(f.getIdMatches().isEmpty());
+
+ f = new Finder(av);
+ f.findNext("d", false, false);
+ assertTrue(f.getIdMatches().isEmpty());
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
match = searchResults.getResults().get(0);
- assertSame(al.getSequenceAt(0), match.getSequence());
- assertEquals(2, match.getStart());
- assertEquals(3, match.getEnd());
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 4);
+ assertEquals(match.getEnd(), 4);
+ f.findNext("d", false, false);
+ assertTrue(f.getIdMatches().isEmpty());
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(2));
+ assertEquals(match.getStart(), 3);
+ assertEquals(match.getEnd(), 3);
+ }
+
+ /**
+ * Test finding all matches of a search pattern in a selection group
+ */
+ @Test(groups = "Functional")
+ public void testFind_findAllInSelection()
+ {
+ /*
+ * select sequences 2 and 3, columns 4-6 which contains
+ * BCD
+ * cdE
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(3);
+ sg.setEndRes(5);
+ sg.addSequence(al.getSequenceAt(1), false);
+ sg.addSequence(al.getSequenceAt(2), false);
+ av.setSelectionGroup(sg);
+
+ /*
+ * search for 'e' should match two sequence ids and one residue
+ */
+ Finder f = new Finder(av);
+ f.findAll("e", false, false);
+ assertEquals(f.getIdMatches().size(), 2);
+ assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
+ assertSame(f.getIdMatches().get(1), al.getSequenceAt(2));
+ SearchResultsI searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(2));
+ assertEquals(match.getStart(), 4);
+ assertEquals(match.getEnd(), 4);
+
+ /*
+ * search for 'Q' should match two sequence ids only
+ */
+ f = new Finder(av);
+ f.findAll("Q", false, false);
+ assertEquals(f.getIdMatches().size(), 2);
+ assertSame(f.getIdMatches().get(0), al.getSequenceAt(1));
+ assertSame(f.getIdMatches().get(1), al.getSequenceAt(2));
+ assertTrue(f.getSearchResults().isEmpty());
+ }
+
+ /**
+ * Test finding in selection with a sequence too short to reach it
+ */
+ @Test(groups = "Functional")
+ public void testFind_findAllInSelectionWithShortSequence()
+ {
+ /*
+ * select all sequences, columns 10-12
+ * BCD
+ * cdE
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.setStartRes(9);
+ sg.setEndRes(11);
+ sg.addSequence(al.getSequenceAt(0), false);
+ sg.addSequence(al.getSequenceAt(1), false);
+ sg.addSequence(al.getSequenceAt(2), false);
+ sg.addSequence(al.getSequenceAt(3), false);
+ av.setSelectionGroup(sg);
+
+ /*
+ * search for 'I' should match two sequence positions
+ */
+ Finder f = new Finder(av);
+ f.findAll("I", false, false);
+ assertTrue(f.getIdMatches().isEmpty());
+ SearchResultsI searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 2);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(0));
+ assertEquals(match.getStart(), 16);
+ assertEquals(match.getEnd(), 16);
match = searchResults.getResults().get(1);
- assertSame(al.getSequenceAt(1), match.getSequence());
- assertEquals(2, match.getStart());
- assertEquals(3, match.getEnd());
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 8);
+ assertEquals(match.getEnd(), 8);
}
/**
- * Test for JAL-2302 to verify that sub-matches are not included in a find all
- * result
+ * Test that find does not report hidden positions
*/
@Test(groups = "Functional")
- public void testFind_maximalResultOnly()
+ public void testFind_withHiddenColumns()
{
- Finder f = new Finder(al, null);
- f.setFindAll(true);
- f.find("M+");
+ /*
+ * 0 5 9
+ * ABCD--EF-GHI
+ * A--BCDefHI
+ * --bcdEFH
+ * aa---aMMMMMaaa
+ */
+
+ /*
+ * hide 2-4 (CD- -BC bcd ---)
+ */
+ HiddenColumns hc = new HiddenColumns();
+ hc.hideColumns(2, 4);
+ al.setHiddenColumns(hc);
+
+ /*
+ * find all search for D should ignore hidden positions in seq1 and seq3,
+ * find the visible D in seq2
+ */
+ Finder f = new Finder(av);
+ f.findAll("D", false, false);
SearchResultsI searchResults = f.getSearchResults();
assertEquals(searchResults.getSize(), 1);
SearchResultMatchI match = searchResults.getResults().get(0);
- assertSame(al.getSequenceAt(3), match.getSequence());
- assertEquals(4, match.getStart()); // dataset sequence positions
- assertEquals(8, match.getEnd()); // base 1
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 4);
+ assertEquals(match.getEnd(), 4);
+
+ /*
+ * hide columns 2-5:
+ * find all 'aaa' should find end of seq4 only
+ */
+ hc.hideColumns(2, 5);
+ f = new Finder(av);
+ f.findAll("aaa", false, false);
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(3));
+ assertEquals(match.getStart(), 9);
+ assertEquals(match.getEnd(), 11);
+
+ /*
+ * find all 'BE' should not match across hidden columns in seq1
+ */
+ f.findAll("BE", false, false);
+ assertTrue(f.getSearchResults().isEmpty());
+
+ /*
+ * boundary case: hide columns at end of alignment
+ * search for H should match seq3/6 only
+ */
+ hc.revealAllHiddenColumns(new ColumnSelection());
+ hc.hideColumns(8, 13);
+ f = new Finder(av);
+ f.findNext("H", false, false);
+ searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 1);
+ match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(2));
+ assertEquals(match.getStart(), 6);
+ assertEquals(match.getEnd(), 6);
+ }
+
+ @Test(groups = "Functional")
+ public void testFind_withHiddenColumnsAndSelection()
+ {
+ /*
+ * 0 5 9
+ * ABCD--EF-GHI
+ * A--BCDefHI
+ * --bcdEFH
+ * aa---aMMMMMaaa
+ */
+
+ /*
+ * hide columns 2-4 and 6-7
+ */
+ HiddenColumns hc = new HiddenColumns();
+ hc.hideColumns(2, 4);
+ hc.hideColumns(6, 7);
+ al.setHiddenColumns(hc);
+
+ /*
+ * select rows 2-3
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.addSequence(al.getSequenceAt(1), false);
+ sg.addSequence(al.getSequenceAt(2), false);
+ sg.setStartRes(0);
+ sg.setEndRes(13);
+ av.setSelectionGroup(sg);
+
+ /*
+ * find all search for A or H
+ * should match seq2/1, seq2/7, not seq3/6
+ */
+ Finder f = new Finder(av);
+ f.findAll("[AH]", false, false);
+ SearchResultsI searchResults = f.getSearchResults();
+ assertEquals(searchResults.getSize(), 2);
+ SearchResultMatchI match = searchResults.getResults().get(0);
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 1);
+ assertEquals(match.getEnd(), 1);
+ match = searchResults.getResults().get(1);
+ assertSame(match.getSequence(), al.getSequenceAt(1));
+ assertEquals(match.getStart(), 7);
+ assertEquals(match.getEnd(), 7);
}
}
import jalview.analysis.Finder;
import jalview.api.AlignViewControllerI;
import jalview.api.FeatureColourI;
+import jalview.api.FinderI;
import jalview.datamodel.Alignment;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
/*
* test Match/Find works first
*/
- Finder f = new Finder(af.getViewport().getAlignment(), null);
- f.setFindAll(true);
- f.setCaseSensitive(true);
- f.find("M+");
+ FinderI f = new Finder(af.getViewport());
+ f.findAll("M+", true, false);
assertEquals(
"Finder found different set of results to manually created SearchResults",
sr, f.getSearchResults());
assertEquals(5, m.getEnd());
}
+ @Test(groups = { "Functional" })
+ public void testMatchContains()
+ {
+ SequenceI seq1 = new Sequence("", "abcdefghijklm");
+ SequenceI seq2 = new Sequence("", "abcdefghijklm");
+ SearchResultMatchI m = new SearchResults().new Match(seq1, 2, 5);
+
+ assertTrue(m.contains(seq1, 2, 5));
+ assertTrue(m.contains(seq1, 3, 5));
+ assertTrue(m.contains(seq1, 2, 4));
+ assertTrue(m.contains(seq1, 3, 3));
+
+ assertFalse(m.contains(seq1, 2, 6));
+ assertFalse(m.contains(seq1, 1, 5));
+ assertFalse(m.contains(seq1, 1, 8));
+ assertFalse(m.contains(seq2, 3, 3));
+ assertFalse(m.contains(null, 3, 3));
+ }
+
/**
* test markColumns for creating column selections
*/
"Didn't set expected number of columns in total for two successive marks",
2, tbs.cardinality());
}
+
+ /**
+ * Test to verify adding doesn't create duplicate results
+ */
+ @Test(groups = { "Functional" })
+ public void testAddResult()
+ {
+ SequenceI seq1 = new Sequence("", "abcdefghijklm");
+ SearchResultsI sr = new SearchResults();
+ sr.addResult(seq1, 3, 5);
+ assertEquals(1, sr.getSize());
+ sr.addResult(seq1, 3, 5);
+ assertEquals(1, sr.getSize());
+ sr.addResult(seq1, 3, 6);
+ assertEquals(2, sr.getSize());
+ }
}