1 package jalview.datamodel.features;
3 import jalview.datamodel.SequenceFeature;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.Collections;
8 import java.util.HashSet;
11 import java.util.Map.Entry;
13 import java.util.TreeMap;
16 * A class that stores sequence features in a way that supports efficient
17 * querying by type and location (overlap). Intended for (but not limited to)
18 * storage of features for one sequence.
23 public class SequenceFeatures implements SequenceFeaturesI
27 * map from feature type to structured store of features for that type
28 * null types are permitted (but not a good idea!)
30 private Map<String, FeatureStore> featureStore;
35 public SequenceFeatures()
38 * use a TreeMap so that features are returned in alphabetical order of type
39 * wrap as a synchronized map for add and delete operations
41 featureStore = Collections
42 .synchronizedSortedMap(new TreeMap<String, FeatureStore>());
49 public boolean add(SequenceFeature sf)
51 String type = sf.getType();
54 System.err.println("Feature type may not be null: " + sf.toString());
58 if (featureStore.get(type) == null)
60 featureStore.put(type, new FeatureStore());
62 return featureStore.get(type).addFeature(sf);
69 public List<SequenceFeature> findFeatures(int from, int to,
72 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
74 for (String featureType : varargToTypes(type))
76 FeatureStore features = featureStore.get(featureType);
79 result.addAll(features.findOverlappingFeatures(from, to));
90 public List<SequenceFeature> getAllFeatures(String... type)
92 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
94 result.addAll(getPositionalFeatures(type));
96 result.addAll(getNonPositionalFeatures(type));
105 public int getFeatureCount(boolean positional, String... type)
109 for (String featureType : varargToTypes(type))
111 FeatureStore featureSet = featureStore.get(featureType);
112 if (featureSet != null)
114 result += featureSet.getFeatureCount(positional);
124 public int getTotalFeatureLength(String... type)
128 for (String featureType : varargToTypes(type))
130 FeatureStore featureSet = featureStore.get(featureType);
131 if (featureSet != null)
133 result += featureSet.getTotalFeatureLength();
144 public List<SequenceFeature> getPositionalFeatures(String... type)
146 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
148 for (String featureType : varargToTypes(type))
150 FeatureStore featureSet = featureStore.get(featureType);
151 if (featureSet != null)
153 result.addAll(featureSet.getPositionalFeatures());
160 * A convenience method that converts a vararg for feature types to an
161 * Iterable, replacing the value with the stored feature types if it is null
167 protected Iterable<String> varargToTypes(String... type)
169 if (type == null || type.length == 0)
172 * no vararg parameter supplied
174 return featureStore.keySet();
178 * else make a copy of the list, and remove any null value just in case,
179 * as it would cause errors looking up the features Map
181 List<String> types = new ArrayList<String>(Arrays.asList(type));
190 public List<SequenceFeature> getContactFeatures(String... type)
192 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
194 for (String featureType : varargToTypes(type))
196 FeatureStore featureSet = featureStore.get(featureType);
197 if (featureSet != null)
199 result.addAll(featureSet.getContactFeatures());
209 public List<SequenceFeature> getNonPositionalFeatures(String... type)
211 List<SequenceFeature> result = new ArrayList<SequenceFeature>();
213 for (String featureType : varargToTypes(type))
215 FeatureStore featureSet = featureStore.get(featureType);
216 if (featureSet != null)
218 result.addAll(featureSet.getNonPositionalFeatures());
228 public boolean delete(SequenceFeature sf)
230 for (FeatureStore featureSet : featureStore.values())
232 if (featureSet.delete(sf))
244 public boolean hasFeatures()
246 for (FeatureStore featureSet : featureStore.values())
248 if (!featureSet.isEmpty())
260 public Set<String> getFeatureGroups(boolean positionalFeatures,
263 Set<String> groups = new HashSet<String>();
265 Iterable<String> types = varargToTypes(type);
267 for (String featureType : types)
269 FeatureStore featureSet = featureStore.get(featureType);
270 if (featureSet != null)
272 groups.addAll(featureSet.getFeatureGroups(positionalFeatures));
283 public Set<String> getFeatureTypesForGroups(boolean positionalFeatures,
286 Set<String> result = new HashSet<String>();
288 for (Entry<String, FeatureStore> featureType : featureStore.entrySet())
290 Set<String> featureGroups = featureType.getValue().getFeatureGroups(
292 for (String group : groups)
294 if (featureGroups.contains(group))
297 * yes this feature type includes one of the query groups
299 result.add(featureType.getKey());
312 public Set<String> getFeatureTypes()
314 Set<String> types = new HashSet<String>();
315 for (Entry<String, FeatureStore> entry : featureStore.entrySet())
317 if (!entry.getValue().isEmpty())
319 types.add(entry.getKey());
329 public float getMinimumScore(String type, boolean positional)
331 return featureStore.containsKey(type) ? featureStore.get(type)
332 .getMinimumScore(positional) : Float.NaN;
339 public float getMaximumScore(String type, boolean positional)
341 return featureStore.containsKey(type) ? featureStore.get(type)
342 .getMaximumScore(positional) : Float.NaN;