1 package jalview.datamodel.features;
3 import jalview.datamodel.SequenceFeature;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.HashSet;
11 import java.util.Map.Entry;
15 * A class that stores sequence features in a way that supports efficient
16 * querying by type and location (overlap). Intended for (but not limited to)
17 * storage of features for one sequence.
22 public class SequenceFeatures
26 * map from feature type to structured store of features for that type
27 * null types are permitted (but not a good idea!)
29 private Map<String, FeatureStore> featureStore;
34 public SequenceFeatures()
36 featureStore = new HashMap<String, FeatureStore>();
40 * Adds one sequence feature to the store, and returns true, unless the
41 * feature is already contained in the store, in which case this method
42 * returns false. Containment is determined by SequenceFeature.equals()
47 public boolean add(SequenceFeature sf)
49 String type = sf.getType();
51 if (featureStore.get(type) == null)
53 featureStore.put(type, new FeatureStore());
55 return featureStore.get(type).addFeature(sf);
59 * Returns a (possibly empty) list of features, optionally restricted to
60 * specified types, which overlap the given (inclusive) sequence position
68 public List<SequenceFeature> findFeatures(int from, int to,
71 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
73 for (String featureType : varargToTypes(type))
75 FeatureStore features = featureStore.get(featureType);
78 result.addAll(features.findOverlappingFeatures(from, to));
86 * Answers a list of all features stored, optionally restricted to specified
87 * types, in no particular guaranteed order
92 public List<SequenceFeature> getAllFeatures(String... type)
94 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
96 result.addAll(getPositionalFeatures(type));
98 result.addAll(getNonPositionalFeatures(type));
104 * Answers a list of all positional features, optionally restricted to
105 * specified types, in no particular guaranteed order
110 public List<SequenceFeature> getPositionalFeatures(String... type)
112 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
114 for (String featureType : varargToTypes(type))
116 FeatureStore featureSet = featureStore.get(featureType);
117 if (featureSet != null)
119 result.addAll(featureSet.getPositionalFeatures());
126 * A convenience method that converts a vararg for feature types to an
127 * Iterable, replacing the value with the stored feature types if it is null
133 protected Iterable<String> varargToTypes(String... type)
135 return type == null || type.length == 0 ? featureStore
136 .keySet() : Arrays.asList(type);
140 * Answers a list of all contact features, optionally restricted to specified
141 * types, in no particular guaranteed order
145 public List<SequenceFeature> getContactFeatures(String... type)
147 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
149 for (String featureType : varargToTypes(type))
151 FeatureStore featureSet = featureStore.get(featureType);
152 if (featureSet != null)
154 result.addAll(featureSet.getContactFeatures());
161 * Answers a list of all non-positional features, optionally restricted to
162 * specified types, in no particular guaranteed order
165 * if no type is specified, all are returned
168 public List<SequenceFeature> getNonPositionalFeatures(String... type)
170 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
172 for (String featureType : varargToTypes(type))
174 FeatureStore featureSet = featureStore.get(featureType);
175 if (featureSet != null)
177 result.addAll(featureSet.getNonPositionalFeatures());
184 * Deletes the given feature from the store, returning true if it was found
185 * (and deleted), else false. This method makes no assumption that the feature
186 * is in the 'expected' place in the store, in case it has been modified since
191 public boolean delete(SequenceFeature sf)
193 for (FeatureStore featureSet : featureStore.values())
195 if (featureSet.delete(sf))
204 * Answers true if this store contains at least one feature, else false
208 public boolean hasFeatures()
210 for (FeatureStore featureSet : featureStore.values())
212 if (!featureSet.isEmpty())
221 * Returns a set of the distinct feature groups present in the collection. The
222 * set may include null. The boolean parameter determines whether the groups
223 * for positional or for non-positional features are returned. The optional
224 * type parameter may be used to restrict to groups for specified feature
227 * @param positionalFeatures
231 public Set<String> getFeatureGroups(boolean positionalFeatures,
234 Set<String> groups = new HashSet<String>();
236 Iterable<String> types = varargToTypes(type);
238 for (String featureType : types)
240 FeatureStore featureSet = featureStore.get(featureType);
241 if (featureSet != null)
243 groups.addAll(featureSet.getFeatureGroups(positionalFeatures));
251 * Answers the set of distinct feature types for which there is at least one
252 * feature with one of the given feature group(s). The parameter determines
253 * whether the groups for positional or for non-positional features are
256 * @param positionalFeatures
260 public Set<String> getFeatureTypesForGroups(boolean positionalFeatures,
263 Set<String> result = new HashSet<String>();
265 for (Entry<String, FeatureStore> featureType : featureStore.entrySet())
267 Set<String> featureGroups = featureType.getValue().getFeatureGroups(
269 for (String group : groups)
271 if (featureGroups.contains(group))
274 * yes this feature type includes one of the query groups
276 result.add(featureType.getKey());