X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fviewmodel%2Fseqfeatures%2FFeatureRendererModel.java;h=459a28b001478b10c0fc5caf6eadeb9bf21a7339;hb=0b573ed90b14079f7326281f50c0c9cffdace586;hp=2aadee4ed3942f84d726d63b10c0ea8e661ebbb8;hpb=356260e6aa37640091849355ed97cd4103cc4c6c;p=jalview.git diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index 2aadee4..459a28b 100644 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -23,7 +23,13 @@ package jalview.viewmodel.seqfeatures; import jalview.api.AlignViewportI; import jalview.api.FeatureColourI; import jalview.api.FeaturesDisplayedI; +import jalview.datamodel.AlignedCodonFrame; import jalview.datamodel.AlignmentI; +import jalview.datamodel.MappedFeatures; +import jalview.datamodel.Mapping; +import jalview.datamodel.SearchResultMatchI; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SearchResultsI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.datamodel.features.FeatureMatcherSetI; @@ -37,6 +43,7 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; @@ -320,12 +327,12 @@ public abstract class FeatureRendererModel visibleTypes); /* - * include features unless their feature group is not displayed, or - * they are hidden (have no colour) based on a filter or colour threshold + * include features unless they are hidden (have no colour), based on + * feature group visibility, or a filter or colour threshold */ for (SequenceFeature sf : features) { - if (!featureGroupNotShown(sf) && getColour(sf) != null) + if (getColour(sf) != null) { result.add(sf); } @@ -612,7 +619,7 @@ public abstract class FeatureRendererModel * @param type * @return */ - protected boolean showFeatureOfType(String type) + public boolean showFeatureOfType(String type) { return type == null ? false : (av.getFeaturesDisplayed() == null ? true : av.getFeaturesDisplayed().isVisible(type)); @@ -652,7 +659,7 @@ public abstract class FeatureRendererModel { featureOrder = new Hashtable<>(); } - featureOrder.put(type, new Float(position)); + featureOrder.put(type, Float.valueOf(position)); return position; } @@ -852,7 +859,7 @@ public abstract class FeatureRendererModel } if (newGroupsVisible) { - featureGroups.put(group, new Boolean(true)); + featureGroups.put(group, Boolean.valueOf(true)); return true; } return false; @@ -888,7 +895,7 @@ public abstract class FeatureRendererModel @Override public void setGroupVisibility(String group, boolean visible) { - featureGroups.put(group, new Boolean(visible)); + featureGroups.put(group, Boolean.valueOf(visible)); } @Override @@ -900,7 +907,7 @@ public abstract class FeatureRendererModel for (String gst : toset) { Boolean st = featureGroups.get(gst); - featureGroups.put(gst, new Boolean(visible)); + featureGroups.put(gst, Boolean.valueOf(visible)); if (st != null) { rdrw = rdrw || (visible != st.booleanValue()); @@ -983,7 +990,7 @@ public abstract class FeatureRendererModel * @param sequenceFeature * @return */ - protected boolean featureGroupNotShown(final SequenceFeature sequenceFeature) + public boolean featureGroupNotShown(final SequenceFeature sequenceFeature) { return featureGroups != null && sequenceFeature.featureGroup != null @@ -998,7 +1005,7 @@ public abstract class FeatureRendererModel */ @Override public List findFeaturesAtResidue(SequenceI sequence, - int resNo) + int fromResNo, int toResNo) { List result = new ArrayList<>(); if (!av.areFeaturesDisplayed() || getFeaturesDisplayed() == null) @@ -1011,12 +1018,11 @@ public abstract class FeatureRendererModel * displayed, and feature group is null or the empty string * or marked for display */ - Set visibleFeatures = getFeaturesDisplayed() - .getVisibleFeatures(); + List visibleFeatures = getDisplayedFeatureTypes(); String[] visibleTypes = visibleFeatures .toArray(new String[visibleFeatures.size()]); List features = sequence.getFeatures().findFeatures( - resNo, resNo, visibleTypes); + fromResNo, toResNo, visibleTypes); for (SequenceFeature sf : features) { @@ -1029,11 +1035,11 @@ public abstract class FeatureRendererModel } /** - * Removes from the list of features any that duplicate the location of a - * feature of the same type. Should be used only for features of the same, - * simple, feature colour (which normally implies the same feature type). Does - * not check visibility settings for feature type or feature group. No - * filtering is done if transparency, or any feature filters, are in force. + * Removes from the list of features any whose group is not shown, or that are + * visible and duplicate the location of a visible feature of the same type. + * Should be used only for features of the same, simple, feature colour (which + * normally implies the same feature type). No filtering is done if + * transparency, or any feature filters, are in force. * * @param features */ @@ -1057,6 +1063,11 @@ 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 @@ -1064,7 +1075,8 @@ public abstract class FeatureRendererModel * (checking type and isContactFeature as a fail-safe here, although * currently they are guaranteed to match in this context) */ - if (lastFeature != null && sf.getBegin() == lastFeature.getBegin() + if (lastFeature != null + && sf.getBegin() == lastFeature.getBegin() && sf.getEnd() == lastFeature.getEnd() && sf.isContactFeature() == lastFeature.isContactFeature() && sf.getType().equals(lastFeature.getType())) @@ -1150,6 +1162,126 @@ public abstract class FeatureRendererModel return filter == null ? true : filter.matches(sf); } + /** + * Answers true unless the specified group is set to hidden. Defaults to true + * if group visibility is not set. + * + * @param group + * @return + */ + public boolean isGroupVisible(String group) + { + if (!featureGroups.containsKey(group)) + { + return true; + } + return featureGroups.get(group); + } + + /** + * Orders features in render precedence (last in order is last to render, so + * displayed on top of other features) + * + * @param order + */ + public void orderFeatures(Comparator order) + { + Arrays.sort(renderOrder, order); + } + + @Override + public MappedFeatures findComplementFeaturesAtResidue(SequenceI sequence, + int pos) + { + SequenceI ds = sequence.getDatasetSequence(); + if (ds == null) + { + ds = sequence; + } + final char residue = ds.getCharAt(pos - ds.getStart()); + + List found = new ArrayList<>(); + List mappings = this.av.getAlignment() + .getCodonFrame(sequence); + + /* + * fudge: if no mapping found, check the complementary alignment + * todo: only store in one place? StructureSelectionManager? + */ + if (mappings.isEmpty()) + { + mappings = this.av.getCodingComplement().getAlignment() + .getCodonFrame(sequence); + } + + /* + * todo: direct lookup of CDS for peptide and vice-versa; for now, + * have to search through an unordered list of mappings for a candidate + */ + Mapping mapping = null; + SequenceI mapFrom = null; + + for (AlignedCodonFrame acf : mappings) + { + mapping = acf.getMappingForSequence(sequence); + if (mapping == null || !mapping.getMap().isTripletMap()) + { + continue; // we are only looking for 3:1 or 1:3 mappings + } + SearchResultsI sr = new SearchResults(); + acf.markMappedRegion(ds, pos, sr); + for (SearchResultMatchI match : sr.getResults()) + { + int fromRes = match.getStart(); + int toRes = match.getEnd(); + mapFrom = match.getSequence(); + List fs = findFeaturesAtResidue( + match.getSequence(), fromRes, toRes); + for (SequenceFeature sf : fs) + { + if (!found.contains(sf)) + { + found.add(sf); + } + } + } + + /* + * just take the first mapped features we find + */ + if (!found.isEmpty()) + { + break; + } + } + if (found.isEmpty()) + { + return null; + } + + /* + * sort by renderorder, inefficiently + */ + List result = new ArrayList<>(); + for (String type : renderOrder) + { + for (SequenceFeature sf : found) + { + if (type.equals(sf.getType())) + { + result.add(sf); + if (result.size() == found.size()) + { + return new MappedFeatures(mapping, mapFrom, pos, residue, + result); + } + } + } + } + + return new MappedFeatures(mapping, mapFrom, pos, residue, result); + } + @Override public boolean isVisible(SequenceFeature feature) { @@ -1177,5 +1309,4 @@ public abstract class FeatureRendererModel } return true; } - }