From: gmungoc Date: Mon, 4 Mar 2019 16:44:19 +0000 (+0000) Subject: Merge remote-tracking branch 'origin/bug/JAL-3082selectRegex' into merge/JAL-3082 X-Git-Tag: Release_2_11_0~17^2~76 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=bc18effe68ba80213a6d03ca7e6175adc6be71d6;hp=424648b2e57e45eaa21c006b44828d8fca418581;p=jalview.git Merge remote-tracking branch 'origin/bug/JAL-3082selectRegex' into merge/JAL-3082 --- diff --git a/src/jalview/datamodel/ColumnSelection.java b/src/jalview/datamodel/ColumnSelection.java index 6d620b4..3ccaab8 100644 --- a/src/jalview/datamodel/ColumnSelection.java +++ b/src/jalview/datamodel/ColumnSelection.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.BitSet; import java.util.Collections; import java.util.List; +import java.util.regex.PatternSyntaxException; /** * Data class holding the selected columns and hidden column ranges for a view. @@ -59,7 +60,7 @@ public class ColumnSelection */ IntList() { - order = new ArrayList(); + order = new ArrayList<>(); _uorder = Collections.unmodifiableList(order); selected = new BitSet(); } @@ -230,7 +231,7 @@ public class ColumnSelection */ List getRanges() { - List rlist = new ArrayList(); + List rlist = new ArrayList<>(); if (selected.isEmpty()) { return rlist; @@ -263,7 +264,7 @@ public class ColumnSelection } } - IntList selection = new IntList(); + private IntList selection = new IntList(); /** * Add a column to the selection @@ -533,92 +534,109 @@ public class ColumnSelection return (selection != null && selection.size() > 0); } - public boolean filterAnnotations(Annotation[] annotations, + /** + * Selects columns where the given annotation matches the provided filter + * condition(s). Any existing column selections are first cleared. Answers the + * number of columns added. + * + * @param annotations + * @param filterParams + * @return + */ + public int filterAnnotations(Annotation[] annotations, AnnotationFilterParameter filterParams) { // JBPNote - this method needs to be refactored to become independent of // viewmodel package this.clear(); - int count = 0; + int addedCount = 0; + int column = 0; do { - if (annotations[count] != null) + Annotation ann = annotations[column]; + if (ann != null) { + boolean matched = false; - boolean itemMatched = false; - + /* + * filter may have multiple conditions - + * these are or'd until a match is found + */ if (filterParams .getThresholdType() == AnnotationFilterParameter.ThresholdType.ABOVE_THRESHOLD - && annotations[count].value >= filterParams - .getThresholdValue()) + && ann.value > filterParams.getThresholdValue()) { - itemMatched = true; + matched = true; } - if (filterParams + + if (!matched && filterParams .getThresholdType() == AnnotationFilterParameter.ThresholdType.BELOW_THRESHOLD - && annotations[count].value <= filterParams - .getThresholdValue()) + && ann.value < filterParams.getThresholdValue()) { - itemMatched = true; + matched = true; } - if (filterParams.isFilterAlphaHelix() - && annotations[count].secondaryStructure == 'H') + if (!matched && filterParams.isFilterAlphaHelix() + && ann.secondaryStructure == 'H') { - itemMatched = true; + matched = true; } - if (filterParams.isFilterBetaSheet() - && annotations[count].secondaryStructure == 'E') + if (!matched && filterParams.isFilterBetaSheet() + && ann.secondaryStructure == 'E') { - itemMatched = true; + matched = true; } - if (filterParams.isFilterTurn() - && annotations[count].secondaryStructure == 'S') + if (!matched && filterParams.isFilterTurn() + && ann.secondaryStructure == 'S') { - itemMatched = true; + matched = true; } String regexSearchString = filterParams.getRegexString(); - if (regexSearchString != null - && !filterParams.getRegexSearchFields().isEmpty()) + if (!matched && regexSearchString != null) { List fields = filterParams .getRegexSearchFields(); - try + for (SearchableAnnotationField field : fields) { - if (fields.contains(SearchableAnnotationField.DISPLAY_STRING) - && annotations[count].displayCharacter - .matches(regexSearchString)) + String compareTo = field == SearchableAnnotationField.DISPLAY_STRING + ? ann.displayCharacter // match 'Label' + : ann.description; // and/or 'Description' + if (compareTo != null) { - itemMatched = true; - } - } catch (java.util.regex.PatternSyntaxException pse) - { - if (annotations[count].displayCharacter - .equals(regexSearchString)) - { - itemMatched = true; + try + { + if (compareTo.matches(regexSearchString)) + { + matched = true; + } + } catch (PatternSyntaxException pse) + { + if (compareTo.equals(regexSearchString)) + { + matched = true; + } + } + if (matched) + { + break; + } } } - if (fields.contains(SearchableAnnotationField.DESCRIPTION) - && annotations[count].description != null - && annotations[count].description - .matches(regexSearchString)) - { - itemMatched = true; - } } - if (itemMatched) + if (matched) { - this.addElement(count); + this.addElement(column); + addedCount++; } } - count++; - } while (count < annotations.length); - return false; + column++; + } while (column < annotations.length); + + return addedCount; } /** diff --git a/src/jalview/gui/AnnotationColumnChooser.java b/src/jalview/gui/AnnotationColumnChooser.java index 6924b63..5adecad 100644 --- a/src/jalview/gui/AnnotationColumnChooser.java +++ b/src/jalview/gui/AnnotationColumnChooser.java @@ -33,6 +33,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyEvent; @@ -744,6 +746,15 @@ public class AnnotationColumnChooser extends AnnotationRowFilter } } }); + searchBox.getEditor().getEditorComponent() + .addFocusListener(new FocusAdapter() + { + @Override + public void focusLost(FocusEvent e) + { + searchStringAction(); + } + }); JvSwingUtils.jvInitComponent(displayName, "label.label"); displayName.addActionListener(new ActionListener() @@ -761,7 +772,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter @Override public void actionPerformed(ActionEvent actionEvent) { - discriptionCheckboxAction(); + descriptionCheckboxAction(); } }); @@ -777,7 +788,7 @@ public class AnnotationColumnChooser extends AnnotationRowFilter aColChooser.updateView(); } - public void discriptionCheckboxAction() + public void descriptionCheckboxAction() { aColChooser.setCurrentSearchPanel(this); aColChooser.updateView(); diff --git a/test/jalview/datamodel/ColumnSelectionTest.java b/test/jalview/datamodel/ColumnSelectionTest.java index 8709961..2dda4d3 100644 --- a/test/jalview/datamodel/ColumnSelectionTest.java +++ b/test/jalview/datamodel/ColumnSelectionTest.java @@ -27,6 +27,9 @@ import static org.testng.AssertJUnit.fail; import jalview.analysis.AlignmentGenerator; import jalview.gui.JvOptionPane; +import jalview.viewmodel.annotationfilter.AnnotationFilterParameter; +import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.SearchableAnnotationField; +import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.ThresholdType; import java.util.Arrays; import java.util.BitSet; @@ -598,4 +601,129 @@ public class ColumnSelectionTest assertEquals(sg.getStartRes(), 10); assertEquals(sg.getEndRes(), 19); } + + @Test(groups = { "Functional" }) + public void testFilterAnnotations() + { + ColumnSelection cs = new ColumnSelection(); + + /* + * filter with no conditions clears the selection + */ + Annotation[] anns = new Annotation[] { null }; + AnnotationFilterParameter filter = new AnnotationFilterParameter(); + cs.addElement(3); + int added = cs.filterAnnotations(anns, filter); + assertEquals(0, added); + assertTrue(cs.isEmpty()); + + /* + * select on description (regex) + */ + filter.setRegexString("w.rld"); + filter.addRegexSearchField(SearchableAnnotationField.DESCRIPTION); + Annotation helix = new Annotation("(", "hello", '<', 2f); + Annotation sheet = new Annotation("(", "world", '<', 2f); + added = cs.filterAnnotations(new Annotation[] { null, helix, sheet }, + filter); + assertEquals(1, added); + assertTrue(cs.contains(2)); + + /* + * select on label (invalid regex, exact match) + */ + filter = new AnnotationFilterParameter(); + filter.setRegexString("("); + filter.addRegexSearchField(SearchableAnnotationField.DISPLAY_STRING); + added = cs.filterAnnotations(new Annotation[] { null, helix, sheet }, + filter); + assertEquals(2, added); + assertTrue(cs.contains(1)); + assertTrue(cs.contains(2)); + + /* + * select Helix (secondary structure symbol H) + */ + filter = new AnnotationFilterParameter(); + filter.setFilterAlphaHelix(true); + helix = new Annotation("x", "desc", 'H', 0f); + sheet = new Annotation("x", "desc", 'E', 1f); + Annotation turn = new Annotation("x", "desc", 'S', 2f); + Annotation ann4 = new Annotation("x", "desc", 'Y', 3f); + added = cs + .filterAnnotations(new Annotation[] + { null, helix, sheet, turn, ann4 }, + filter); + assertEquals(1, added); + assertTrue(cs.contains(1)); + + /* + * select Helix and Sheet (E) + */ + filter.setFilterBetaSheet(true); + added = cs + .filterAnnotations(new Annotation[] + { null, helix, sheet, turn, ann4 }, filter); + assertEquals(2, added); + assertTrue(cs.contains(1)); + assertTrue(cs.contains(2)); + + /* + * select Sheet and Turn (S) + */ + filter.setFilterAlphaHelix(false); + filter.setFilterTurn(true); + added = cs + .filterAnnotations(new Annotation[] + { null, helix, sheet, turn, ann4 }, filter); + assertEquals(2, added); + assertTrue(cs.contains(2)); + assertTrue(cs.contains(3)); + + /* + * select value < 2f (ann1, ann2) + */ + filter = new AnnotationFilterParameter(); + filter.setThresholdType(ThresholdType.BELOW_THRESHOLD); + filter.setThresholdValue(2f); + added = cs + .filterAnnotations(new Annotation[] + { null, helix, sheet, turn, ann4 }, filter); + assertEquals(2, added); + assertTrue(cs.contains(1)); + assertTrue(cs.contains(2)); + + /* + * select value > 2f (ann4 only) + */ + filter.setThresholdType(ThresholdType.ABOVE_THRESHOLD); + added = cs + .filterAnnotations(new Annotation[] + { null, helix, sheet, turn, ann4 }, filter); + assertEquals(1, added); + assertTrue(cs.contains(4)); + + /* + * select >2f or Helix + */ + filter.setFilterAlphaHelix(true); + added = cs + .filterAnnotations(new Annotation[] + { null, helix, sheet, turn, ann4 }, filter); + assertEquals(2, added); + assertTrue(cs.contains(1)); + assertTrue(cs.contains(4)); + + /* + * select < 1f or Helix; one annotation matches both + * return value should only count it once + */ + filter.setThresholdType(ThresholdType.BELOW_THRESHOLD); + filter.setThresholdValue(1f); + added = cs + .filterAnnotations(new Annotation[] + { null, helix, sheet, turn, ann4 }, filter); + assertEquals(1, added); + assertTrue(cs.contains(1)); + } }