- for (SequenceFeature sf : getPositionalFeatures())
- {
- positionalFeatureGroups.add(sf.getFeatureGroup());
- float score = sf.getScore();
- positionalMinScore = min(positionalMinScore, score);
- positionalMaxScore = max(positionalMaxScore, score);
- totalExtent += getFeatureLength(sf);
- }
- }
-
- /**
- * A helper method to return the minimum of two floats, where a non-NaN value
- * is treated as 'less than' a NaN value (unlike Math.min which does the
- * opposite)
- *
- * @param f1
- * @param f2
- */
- protected static float min(float f1, float f2)
- {
- if (Float.isNaN(f1))
- {
- return Float.isNaN(f2) ? f1 : f2;
- }
- else
- {
- return Float.isNaN(f2) ? f1 : Math.min(f1, f2);
- }
- }
-
- /**
- * A helper method to return the maximum of two floats, where a non-NaN value
- * is treated as 'greater than' a NaN value (unlike Math.max which does the
- * opposite)
- *
- * @param f1
- * @param f2
- */
- protected static float max(float f1, float f2)
- {
- if (Float.isNaN(f1))
- {
- return Float.isNaN(f2) ? f1 : f2;
- }
- else
- {
- return Float.isNaN(f2) ? f1 : Math.max(f1, f2);
- }
- }
-
- /**
- * Scans all positional features to check whether the given feature group is
- * found, and returns true if found, else false
- *
- * @param featureGroup
- * @return
- */
- protected boolean findFeatureGroup(String featureGroup)
- {
- for (SequenceFeature sf : getPositionalFeatures())
- {
- String group = sf.getFeatureGroup();
- if (group == featureGroup
- || (group != null && group.equals(featureGroup)))
- {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Answers true if this store has no features, else false
- *
- * @return
- */
- public boolean isEmpty()
- {
- boolean hasFeatures = !nonNestedFeatures.isEmpty()
- || (contactFeatureStarts != null && !contactFeatureStarts
- .isEmpty())
- || (nonPositionalFeatures != null && !nonPositionalFeatures
- .isEmpty())
- || (nestedFeatures != null && nestedFeatures.size() > 0);
-
- return !hasFeatures;
- }
-
- /**
- * Answers the set of distinct feature groups stored, possibly including null,
- * as an unmodifiable view of the set. The parameter determines whether the
- * groups for positional or for non-positional features are returned.
- *
- * @param positionalFeatures
- * @return
- */
- public Set<String> getFeatureGroups(boolean positionalFeatures)
- {
- if (positionalFeatures)
- {
- return Collections.unmodifiableSet(positionalFeatureGroups);
- }
- else
- {
- return nonPositionalFeatureGroups == null ? Collections
- .<String> emptySet() : Collections
- .unmodifiableSet(nonPositionalFeatureGroups);
- }
- }
-
- /**
- * Performs a binary search of the (sorted) list to find the index of the
- * first entry which returns true for the given comparator function. Returns
- * the length of the list if there is no such entry.
- *
- * @param features
- * @param sc
- * @return
- */
- protected static int binarySearch(List<SequenceFeature> features,
- SearchCriterion sc)
- {
- int start = 0;
- int end = features.size() - 1;
- int matched = features.size();
-
- while (start <= end)
- {
- int mid = (start + end) / 2;
- SequenceFeature entry = features.get(mid);
- boolean compare = sc.compare(entry);
- if (compare)
- {
- matched = mid;
- end = mid - 1;
- }
- else
- {
- start = mid + 1;
- }
- }
-
- return matched;
- }
-
- /**
- * Answers the number of positional (or non-positional) features stored.
- * Contact features count as 1.
- *
- * @param positional
- * @return
- */
- public int getFeatureCount(boolean positional)
- {
- if (!positional)
- {
- return nonPositionalFeatures == null ? 0 : nonPositionalFeatures
- .size();
- }
-
- int size = nonNestedFeatures.size();
-
- if (contactFeatureStarts != null)
- {
- // note a contact feature (start/end) counts as one
- size += contactFeatureStarts.size();
- }
-
- if (nestedFeatures != null)
- {
- size += nestedFeatures.size();
- }
-
- return size;
- }
-
- /**
- * Answers the total length of positional features (or zero if there are
- * none). Contact features contribute a value of 1 to the total.
- *
- * @return
- */
- public int getTotalFeatureLength()
- {
- return totalExtent;
- }
-
- /**
- * Answers the minimum score held for positional or non-positional features.
- * This may be Float.NaN if there are no features, are none has a non-NaN
- * score.
- *
- * @param positional
- * @return
- */
- public float getMinimumScore(boolean positional)
- {
- return positional ? positionalMinScore : nonPositionalMinScore;
- }