JAL-3383 JAL-3253-applet
authorhansonr <hansonr@STO24954W.ad.stolaf.edu>
Mon, 5 Aug 2019 14:19:59 +0000 (09:19 -0500)
committerhansonr <hansonr@STO24954W.ad.stolaf.edu>
Mon, 5 Aug 2019 14:19:59 +0000 (09:19 -0500)
-adds equivalent of features.contains()
-timing within 0.5 sec for braf.jvp load of human variants.

src/jalview/datamodel/features/FeatureStore.java
src/jalview/datamodel/features/FeatureStoreImpl.java
src/jalview/datamodel/features/FeatureStoreJS.java
src/jalview/datamodel/features/SequenceFeatures.java

index fe575e0..ccd8b66 100644 (file)
@@ -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
index a41633a..02394bb 100644 (file)
@@ -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
index 3afbfb2..bd50420 100644 (file)
@@ -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<SequenceFeature> 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<SequenceFeature>) 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<SequenceFeature>
-  {
-
-    @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<SequenceFeature>
+  // {
+  //
+  // @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<SequenceFeature> result)
   {
-    int n = features.size();
+    int n = featureList.size();
     switch (n)
     {
     case 0:
       return;
     case 1:
-      checkOne(((ArrayList<SequenceFeature>) 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
index 54102ce..0baeb19 100644 (file)
@@ -120,6 +120,10 @@ public class SequenceFeatures implements SequenceFeaturesI
     List<SequenceFeature> 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;