From 9bcdd1d38988de350482acfd1a21628f73cdbd6d Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 2 Nov 2017 14:47:10 +0000 Subject: [PATCH] JAL-2808 feature filters held on FeatureRenderer, getColor(feature) extracted --- src/jalview/api/FeatureRenderer.java | 50 ++++++++ .../renderer/seqfeatures/FeatureRenderer.java | 8 +- .../seqfeatures/FeatureRendererModel.java | 131 ++++++++++++++++---- .../seqfeatures/FeatureRendererSettings.java | 15 +++ 4 files changed, 177 insertions(+), 27 deletions(-) diff --git a/src/jalview/api/FeatureRenderer.java b/src/jalview/api/FeatureRenderer.java index 9d2d7f4..40c7d4d 100644 --- a/src/jalview/api/FeatureRenderer.java +++ b/src/jalview/api/FeatureRenderer.java @@ -22,6 +22,7 @@ package jalview.api; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.util.matcher.KeyedMatcherSetI; import java.awt.Color; import java.awt.Graphics; @@ -215,4 +216,53 @@ public interface FeatureRenderer */ float getTransparency(); + /** + * Answers the filters applied to the given feature type, or null if none is + * set + * + * @param featureType + * @return + */ + KeyedMatcherSetI getFeatureFilter(String featureType); + + /** + * Answers a shallow copy of the feature filters map + * + * @return + */ + public Map getFeatureFilters(); + + /** + * Sets the filters for the feature type, or removes them if a null or empty + * filter is passed + * + * @param featureType + * @param filter + */ + void setFeatureFilter(String featureType, KeyedMatcherSetI filter); + + /** + * Replaces all feature filters with the given map + * + * @param filters + */ + void setFeatureFilters(Map filters); + + /** + * Returns the colour for a particular feature instance. This includes + * calculation of 'colour by label', or of a graduated score colour, if + * applicable. + *

+ * Returns null if + *

    + *
  • feature type is not visible, or
  • + *
  • feature group is not visible, or
  • + *
  • feature values lie outside any colour threshold, or
  • + *
  • feature is excluded by filter conditions
  • + *
+ * + * @param feature + * @return + */ + Color getColour(SequenceFeature feature); } diff --git a/src/jalview/renderer/seqfeatures/FeatureRenderer.java b/src/jalview/renderer/seqfeatures/FeatureRenderer.java index 1f47da3..6687e6a 100644 --- a/src/jalview/renderer/seqfeatures/FeatureRenderer.java +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@ -304,14 +304,16 @@ public class FeatureRenderer extends FeatureRendererModel List overlaps = seq.getFeatures().findFeatures( visiblePositions.getBegin(), visiblePositions.getEnd(), type); - filterFeaturesForDisplay(overlaps, fc); + // filterFeaturesForDisplay(overlaps, fc); for (SequenceFeature sf : overlaps) { - Color featureColour = fc.getColor(sf); + Color featureColour = getColor(sf, fc); if (featureColour == null) { - // score feature outwith threshold for colouring + /* + * feature excluded by visibility settings, filters, or colour threshold + */ continue; } diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index 2f30e94..6461748 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -30,6 +30,7 @@ import jalview.datamodel.features.SequenceFeatures; import jalview.renderer.seqfeatures.FeatureRenderer; import jalview.schemes.FeatureColour; import jalview.util.ColorUtils; +import jalview.util.matcher.KeyedMatcherSetI; import java.awt.Color; import java.beans.PropertyChangeListener; @@ -49,14 +50,25 @@ public abstract class FeatureRendererModel implements jalview.api.FeatureRenderer { - /** + /* * global transparency for feature */ protected float transparency = 1.0f; - protected Map featureColours = new ConcurrentHashMap(); + /* + * colour scheme for each feature type + */ + protected Map featureColours = new ConcurrentHashMap<>(); + + /* + * visibility flag for each feature group + */ + protected Map featureGroups = new ConcurrentHashMap<>(); - protected Map featureGroups = new ConcurrentHashMap(); + /* + * filters for each feature type + */ + protected Map featureFilters = new HashMap<>(); protected String[] renderOrder; @@ -100,6 +112,7 @@ public abstract class FeatureRendererModel this.renderOrder = frs.renderOrder; this.featureGroups = frs.featureGroups; this.featureColours = frs.featureColours; + this.featureFilters = frs.featureFilters; this.transparency = frs.transparency; this.featureOrder = frs.featureOrder; if (av != null && av != fr.getViewport()) @@ -557,20 +570,11 @@ public abstract class FeatureRendererModel return fc; } - /** - * Returns the configured colour for a particular feature instance. This - * includes calculation of 'colour by label', or of a graduated score colour, - * if applicable. It does not take into account feature visibility or colour - * transparency. Returns null for a score feature whose score value lies - * outside any colour threshold. - * - * @param feature - * @return - */ + @Override public Color getColour(SequenceFeature feature) { FeatureColourI fc = getFeatureStyle(feature.getType()); - return fc.getColor(feature); + return getColor(feature, fc); } /** @@ -995,11 +999,11 @@ public abstract class FeatureRendererModel } /** - * Removes from the list of features any that have a feature group that is not - * displayed, or duplicate the location of a feature of the same type (unless - * a graduated colour scheme or colour by label is applied). Should be used - * only for features of the same feature colour (which normally implies the - * same feature type). + * Removes from the list of features any that duplicate the location of a + * feature of the same type (unless feature is filtered out, or a graduated + * colour scheme or colour by label is applied). Should be used only for + * features of the same feature colour (which normally implies the same + * feature type). * * @param features * @param fc @@ -1019,11 +1023,6 @@ public abstract class FeatureRendererModel while (it.hasNext()) { SequenceFeature sf = it.next(); - if (featureGroupNotShown(sf)) - { - it.remove(); - continue; - } /* * a feature is redundant for rendering purposes if it has the @@ -1045,4 +1044,88 @@ public abstract class FeatureRendererModel } } + @Override + public Map getFeatureFilters() + { + return new HashMap<>(featureFilters); + } + + @Override + public void setFeatureFilters(Map filters) + { + featureFilters = filters; + } + + @Override + public KeyedMatcherSetI getFeatureFilter(String featureType) + { + return featureFilters.get(featureType); + } + + @Override + public void setFeatureFilter(String featureType, KeyedMatcherSetI filter) + { + if (filter == null || filter.isEmpty()) + { + featureFilters.remove(featureType); + } + else + { + featureFilters.put(featureType, filter); + } + } + + /** + * Answers the colour for the feature, or null if the feature is excluded by + * feature type or group visibility, by filters, or by colour threshold + * settings + * + * @param sf + * @param fc + * @return + */ + public Color getColor(SequenceFeature sf, FeatureColourI fc) + { + /* + * is the feature type displayed? + */ + if (!showFeatureOfType(sf.getType())) + { + return null; + } + + /* + * is the feature group displayed? + */ + if (featureGroupNotShown(sf)) + { + return null; + } + + /* + * does the feature pass filters? + */ + if (!featureMatchesFilters(sf)) + { + return null; + } + + return fc.getColor(sf); + } + + /** + * Answers true if there no are filters defined for the feature type, or this + * feature matches the filters. Answers false if the feature fails to match + * filters. + * + * @param sf + * @return + */ + protected boolean featureMatchesFilters(SequenceFeature sf) + { + KeyedMatcherSetI filter = featureFilters.get(sf.getType()); + return filter == null ? true : filter.matches(key -> sf + .getValueAsString(key)); + } + } diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java index dc2ae11..6afaa54 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java @@ -22,8 +22,10 @@ package jalview.viewmodel.seqfeatures; import jalview.api.FeatureColourI; import jalview.schemes.FeatureColour; +import jalview.util.matcher.KeyedMatcherSetI; import java.util.Arrays; +import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -42,6 +44,11 @@ public class FeatureRendererSettings implements Cloneable */ Map featureColours; + /* + * map of {featureType, filters} + */ + Map featureFilters; + float transparency; Map featureOrder; @@ -72,7 +79,9 @@ public class FeatureRendererSettings implements Cloneable renderOrder = null; featureGroups = new ConcurrentHashMap(); featureColours = new ConcurrentHashMap(); + featureFilters = new HashMap<>(); featureOrder = new ConcurrentHashMap(); + if (fr.renderOrder != null) { this.renderOrder = new String[fr.renderOrder.length]; @@ -100,6 +109,12 @@ public class FeatureRendererSettings implements Cloneable featureColours.put(next, new FeatureColour((FeatureColour) val)); } } + + if (fr.featureFilters != null) + { + this.featureFilters.putAll(fr.featureFilters); + } + this.transparency = fr.transparency; if (fr.featureOrder != null) { -- 1.7.10.2