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.
*/
IntList()
{
- order = new ArrayList<Integer>();
+ order = new ArrayList<>();
_uorder = Collections.unmodifiableList(order);
selected = new BitSet();
}
*/
List<int[]> getRanges()
{
- List<int[]> rlist = new ArrayList<int[]>();
+ List<int[]> rlist = new ArrayList<>();
if (selected.isEmpty())
{
return rlist;
}
}
- IntList selection = new IntList();
+ private IntList selection = new IntList();
/**
* Add a column to the selection
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<SearchableAnnotationField> 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;
}
/**
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;
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));
+ }
}