From 8406f2ced29d2c04dbabaf1cde80b1a7fa8ce8ce Mon Sep 17 00:00:00 2001 From: hansonr Date: Mon, 5 Aug 2019 09:19:59 -0500 Subject: [PATCH] JAL-3383 JAL-3253-applet -adds equivalent of features.contains() -timing within 0.5 sec for braf.jvp load of human variants. --- src/jalview/datamodel/features/FeatureStore.java | 10 +- .../datamodel/features/FeatureStoreImpl.java | 16 +++ src/jalview/datamodel/features/FeatureStoreJS.java | 102 +++++++++++++------- .../datamodel/features/SequenceFeatures.java | 4 + 4 files changed, 90 insertions(+), 42 deletions(-) diff --git a/src/jalview/datamodel/features/FeatureStore.java b/src/jalview/datamodel/features/FeatureStore.java index fe575e0..ccd8b66 100644 --- a/src/jalview/datamodel/features/FeatureStore.java +++ b/src/jalview/datamodel/features/FeatureStore.java @@ -316,10 +316,7 @@ public abstract class FeatureStore implements FeatureStoreI * Adds one feature to the IntervalStore that can manage nested features * (creating the IntervalStore if necessary) */ - protected synchronized void addNestedFeature(SequenceFeature feature) - { - features.add(feature); - } + abstract protected void addNestedFeature(SequenceFeature feature); /** * Adds the feature to the list of non-positional features (with lazy @@ -366,9 +363,12 @@ public abstract class FeatureStore implements FeatureStoreI && listContains(contactFeatureStarts, feature); } - return features == null ? false : features.contains(feature); + return features == null ? false : containsFeature(feature); } + + abstract protected boolean containsFeature(SequenceFeature feature); + /** * Deletes the given feature from the store, returning true if it was found * (and deleted), else false. This method makes no assumption that the feature diff --git a/src/jalview/datamodel/features/FeatureStoreImpl.java b/src/jalview/datamodel/features/FeatureStoreImpl.java index a41633a..02394bb 100644 --- a/src/jalview/datamodel/features/FeatureStoreImpl.java +++ b/src/jalview/datamodel/features/FeatureStoreImpl.java @@ -83,6 +83,16 @@ public class FeatureStoreImpl extends FeatureStore } /** + * Adds one feature to the IntervalStore that can manage nested features + * (creating the IntervalStore if necessary) + */ + @Override + protected synchronized void addNestedFeature(SequenceFeature feature) + { + features.add(feature); + } + + /** * Adds contact features to the result list where either the second or the * first contact position lies within the target range * @@ -101,6 +111,12 @@ public class FeatureStoreImpl extends FeatureStore } } + @Override + protected boolean containsFeature(SequenceFeature feature) + { + return features.contains(feature); + } + /** * Adds to the result list any contact features whose end (second contact * point), but not start (first contact point), lies in the query from-to diff --git a/src/jalview/datamodel/features/FeatureStoreJS.java b/src/jalview/datamodel/features/FeatureStoreJS.java index 3afbfb2..bd50420 100644 --- a/src/jalview/datamodel/features/FeatureStoreJS.java +++ b/src/jalview/datamodel/features/FeatureStoreJS.java @@ -23,8 +23,6 @@ package jalview.datamodel.features; import jalview.datamodel.SequenceFeature; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; import java.util.List; /** @@ -40,11 +38,16 @@ public class FeatureStoreJS extends FeatureStore boolean contactsTainted = true; /** + * internal reference to features as an ArrayList + */ + private ArrayList featureList; + + /** * Constructor */ public FeatureStoreJS() { - features = new ArrayList<>(); + features = featureList = new ArrayList<>(); } /** @@ -72,6 +75,16 @@ public class FeatureStoreJS extends FeatureStore } /** + * Adds one feature to the IntervalStore that can manage nested features + * (creating the IntervalStore if necessary) + */ + @Override + protected synchronized void addNestedFeature(SequenceFeature feature) + { + featureList.add(findFirstBegin(featureList, feature.begin), feature); + } + + /** * Returns a (possibly empty) list of features whose extent overlaps the given * range. The returned list is not ordered. Contact features are included if * either of the contact points lies within the range. @@ -103,7 +116,7 @@ public class FeatureStoreJS extends FeatureStore findContactFeatures(start, end, result); } } - if (features.size() > 0) + if (featureList.size() > 0) { findOverlaps(start, end, result); } @@ -140,38 +153,29 @@ public class FeatureStoreJS extends FeatureStore private void rebuildArrays(int n) { - if (startComp == null) - { - startComp = new StartComparator(); - } - orderedFeatureStarts = new SequenceFeature[n]; - for (int i = n; --i >= 0;) - { - SequenceFeature sf = ((ArrayList) features).get(i); - sf.index = i; // for debugging only - orderedFeatureStarts[i] = sf; - } - Arrays.sort(orderedFeatureStarts, startComp); + // Arrays.sort(orderedFeatureStarts, startComp); + orderedFeatureStarts = featureList + .toArray(new SequenceFeature[featureList.size()]); linkFeatures(orderedFeatureStarts); } - /** - * just a standard Comparator - */ - private static StartComparator startComp; - - class StartComparator implements Comparator - { - - @Override - public int compare(SequenceFeature o1, SequenceFeature o2) - { - int p1 = o1.begin; - int p2 = o2.begin; - return (p1 < p2 ? -1 : p1 > p2 ? 1 : 0); - } - - } + // /** + // * just a standard Comparator + // */ + // private static StartComparator startComp; + // + // class StartComparator implements Comparator + // { + // + // @Override + // public int compare(SequenceFeature o1, SequenceFeature o2) + // { + // int p1 = o1.begin; + // int p2 = o2.begin; + // return (p1 < p2 ? -1 : p1 > p2 ? 1 : 0); + // } + // + // } /** * Run through the sorted sequence array once, building the containedBy linked @@ -283,20 +287,20 @@ public class FeatureStoreJS extends FeatureStore * Find all overlaps; special case when there is only one feature. The * required array of start-sorted SequenceFeature is created lazily. * - * @param features - * @param pos + * @param start + * @param end * @param result */ private void findOverlaps(long start, long end, List result) { - int n = features.size(); + int n = featureList.size(); switch (n) { case 0: return; case 1: - checkOne(((ArrayList) features).get(0), start, end, + checkOne(featureList.get(0), start, end, result); return; default: @@ -357,6 +361,30 @@ public class FeatureStoreJS extends FeatureStore return; } + @Override + protected boolean containsFeature(SequenceFeature feature) + { + + int pos = findFirstBegin(featureList, + feature.begin); + int len = featureList.size(); + while (pos < len) + { + SequenceFeature sf = featureList.get(pos); + if (sf.begin > feature.begin) + { + return false; // no match found + } + if (sf.equals(feature)) + { + return true; + } + pos++; + } + return false; + + } + /** * A binary search identical to the one used for contact start/end, but here * we return the feature itself. Unlike Collection.BinarySearch, all we have diff --git a/src/jalview/datamodel/features/SequenceFeatures.java b/src/jalview/datamodel/features/SequenceFeatures.java index 54102ce..0baeb19 100644 --- a/src/jalview/datamodel/features/SequenceFeatures.java +++ b/src/jalview/datamodel/features/SequenceFeatures.java @@ -120,6 +120,10 @@ public class SequenceFeatures implements SequenceFeaturesI List result = new ArrayList<>(); for (FeatureStoreI featureSet : varargToTypes(type)) { +// System.err.println("SF findFeature " + System.currentTimeMillis() +// + " " + from + " " + to + " " +// + featureSet.getPositionalFeatures().get(0).type); +// result.addAll(featureSet.findOverlappingFeatures(from, to, null)); } return result; -- 1.7.10.2