- if (features == null || feature == null)
- {
- return false;
- }
-
- /*
- * locate the first entry in the list which does not precede the feature
- */
- // int pos = binarySearch(features,
- // SearchCriterion.byFeature(feature, RangeComparator.BY_START_POSITION));
- int pos = BinarySearcher.findFirst(features,
- val -> val.getBegin() >= feature.getBegin());
- int len = features.size();
- while (pos < len)
- {
- SequenceFeature sf = features.get(pos);
- if (sf.getBegin() > feature.getBegin())
- {
- return false; // no match found
- }
- if (sf.equals(feature))
- {
- return true;
- }
- pos++;
- }
- return false;
- }
-
- /**
- * 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.
- *
- * @param start
- * start position of overlap range (inclusive)
- * @param end
- * end position of overlap range (inclusive)
- * @return
- */
- public List<SequenceFeature> findOverlappingFeatures(long start, long end)
- {
- List<SequenceFeature> result = new ArrayList<>();
-
- findContactFeatures(start, end, result);
-
- if (features != null)
- {
- result.addAll(features.findOverlaps(start, end));
- }
-
- return result;
- }
-
- /**
- * Adds contact features to the result list where either the second or the
- * first contact position lies within the target range
- *
- * @param from
- * @param to
- * @param result
- */
- protected void findContactFeatures(long from, long to,
- List<SequenceFeature> result)
- {
- if (contactFeatureStarts != null)
- {
- findContactStartOverlaps(from, to, result);
- }
- if (contactFeatureEnds != null)
- {
- findContactEndOverlaps(from, to, result);
- }
- }
-
- /**
- * 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
- * range
- *
- * @param from
- * @param to
- * @param result
- */
- protected void findContactEndOverlaps(long from, long to,
- List<SequenceFeature> result)
- {
- /*
- * find the first contact feature (if any)
- * whose end point is not before the target range
- */
- int index = BinarySearcher.findFirst(contactFeatureEnds,
- f -> f.getEnd() >= from);
-
- while (index < contactFeatureEnds.size())
- {
- SequenceFeature sf = contactFeatureEnds.get(index);
- if (!sf.isContactFeature())
- {
- System.err.println("Error! non-contact feature type "
- + sf.getType() + " in contact features list");
- index++;
- continue;
- }
-
- int begin = sf.getBegin();
- if (begin >= from && begin <= to)
- {
- /*
- * this feature's first contact position lies in the search range
- * so we don't include it in results a second time
- */
- index++;
- continue;
- }
-
- if (sf.getEnd() > to)
- {
- /*
- * this feature (and all following) has end point after the target range
- */
- break;
- }
-
- /*
- * feature has end >= from and end <= to
- * i.e. contact end point lies within overlap search range
- */
- result.add(sf);
- index++;
- }
- }
-
- /**
- * Adds contact features whose start position lies in the from-to range to the
- * result list
- *
- * @param from
- * @param to
- * @param result
- */
- protected void findContactStartOverlaps(long from, long to,
- List<SequenceFeature> result)
- {
- int index = BinarySearcher.findFirst(contactFeatureStarts,
- f -> f.getBegin() >= from);
-
- while (index < contactFeatureStarts.size())
- {
- SequenceFeature sf = contactFeatureStarts.get(index);
- if (!sf.isContactFeature())
- {
- System.err.println("Error! non-contact feature " + sf.toString()
- + " in contact features list");
- index++;
- continue;
- }
- if (sf.getBegin() > to)
- {
- /*
- * this feature's start (and all following) follows the target range
- */
- break;
- }
-
- /*
- * feature has begin >= from and begin <= to
- * i.e. contact start point lies within overlap search range
- */
- result.add(sf);
- index++;
- }
- }
-
- /**
- * Answers a list of all positional features stored, in no guaranteed order
- *
- * @return
- */
- public List<SequenceFeature> getPositionalFeatures()
- {
- List<SequenceFeature> result = new ArrayList<>();
-
- /*
- * add any contact features - from the list by start position
- */
- if (contactFeatureStarts != null)
- {
- result.addAll(contactFeatureStarts);
- }
-
- /*
- * add any nested features
- */
- if (features != null)
- {
- result.addAll(features);
- }
-
- return result;
- }
-
- /**
- * Answers a list of all contact features. If there are none, returns an
- * immutable empty list.
- *
- * @return
- */
- public List<SequenceFeature> getContactFeatures()
- {
- if (contactFeatureStarts == null)
- {
- return Collections.emptyList();
- }
- return new ArrayList<>(contactFeatureStarts);
- }
-
- /**
- * Answers a list of all non-positional features. If there are none, returns
- * an immutable empty list.
- *
- * @return
- */
- public List<SequenceFeature> getNonPositionalFeatures()
- {
- if (nonPositionalFeatures == null)
- {
- return Collections.emptyList();
- }
- return new ArrayList<>(nonPositionalFeatures);
- }