}
/**
- * Answers the number of positional (or non-positional) features stored
+ * Answers the number of positional (or non-positional) features stored.
+ * Contact features count as 1.
*
* @param positional
* @return
*/
- public int size(boolean positional)
+ public int getFeatureCount(boolean positional)
{
if (!positional)
{
}
/**
- * Answers the average length of positional features (or zero if there are
- * none). Contact features contribute a value of 1 to the average.
+ * 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 float getAverageFeatureLength()
+ public int getTotalFeatureLength()
{
- int d = size(true);
- return d == 0 ? 0f : (float) totalExtent / d;
+ return totalExtent;
}
}
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
featureStore = new HashMap<String, FeatureStore>();
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#add(jalview.datamodel.SequenceFeature)
+ /**
+ * {@inheritDoc}
*/
@Override
public boolean add(SequenceFeature sf)
return featureStore.get(type).addFeature(sf);
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#findFeatures(int, int, java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public List<SequenceFeature> findFeatures(int from, int to,
return result;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getAllFeatures(java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public List<SequenceFeature> getAllFeatures(String... type)
return result;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getFeatureCount(boolean, java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public int getFeatureCount(boolean positional, String... type)
{
int result = 0;
- for (FeatureStore fs : featureStore.values())
+
+ for (String featureType : varargToTypes(type))
{
- result += fs.size(positional);
+ FeatureStore featureSet = featureStore.get(featureType);
+ if (featureSet != null)
+ {
+ result += featureSet.getFeatureCount(positional);
+ }
}
-
return result;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getPositionalFeatures(java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public List<SequenceFeature> getPositionalFeatures(String... type)
.keySet() : Arrays.asList(type);
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getContactFeatures(java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public List<SequenceFeature> getContactFeatures(String... type)
return result;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getNonPositionalFeatures(java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public List<SequenceFeature> getNonPositionalFeatures(String... type)
return result;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#delete(jalview.datamodel.SequenceFeature)
+ /**
+ * {@inheritDoc}
*/
@Override
public boolean delete(SequenceFeature sf)
return false;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#hasFeatures()
+ /**
+ * {@inheritDoc}
*/
@Override
public boolean hasFeatures()
return false;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getFeatureGroups(boolean, java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public Set<String> getFeatureGroups(boolean positionalFeatures,
return groups;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getFeatureTypesForGroups(boolean, java.lang.String)
+ /**
+ * {@inheritDoc}
*/
@Override
public Set<String> getFeatureTypesForGroups(boolean positionalFeatures,
return result;
}
- /* (non-Javadoc)
- * @see jalview.datamodel.features.SequenceFeaturesI#getFeatureTypes()
+ /**
+ * {@inheritDoc}
*/
@Override
public Set<String> getFeatureTypes()
{
- return Collections.unmodifiableSet(featureStore.keySet());
+ Set<String> types = new HashSet<String>();
+ for (Entry<String, FeatureStore> entry : featureStore.entrySet())
+ {
+ if (!entry.getValue().isEmpty())
+ {
+ types.add(entry.getKey());
+ }
+ }
+ return types;
}
}
boolean positionalFeatures, String... groups);
/**
- * Answers an immutable set of the distinct feature types for which a feature
- * is stored
+ * Answers a set of the distinct feature types for which a feature is stored
+ *
* @return
*/
public abstract Set<String> getFeatureTypes();
Float.NaN, null);
assertTrue(fs.addFeature(sf1));
- assertEquals(fs.size(true), 1); // positional
- assertEquals(fs.size(false), 0); // non-positional
+ assertEquals(fs.getFeatureCount(true), 1); // positional
+ assertEquals(fs.getFeatureCount(false), 0); // non-positional
/*
* re-adding the same or an identical feature should fail
*/
assertFalse(fs.addFeature(sf1));
- assertEquals(fs.size(true), 1);
+ assertEquals(fs.getFeatureCount(true), 1);
assertFalse(fs.addFeature(sf2));
- assertEquals(fs.size(true), 1);
+ assertEquals(fs.getFeatureCount(true), 1);
+
+ /*
+ * add non-positional
+ */
+ SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
+ null);
+ assertTrue(fs.addFeature(sf3));
+ assertEquals(fs.getFeatureCount(true), 1); // positional
+ assertEquals(fs.getFeatureCount(false), 1); // non-positional
+ SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
+ null);
+ assertFalse(fs.addFeature(sf4)); // already stored
+ assertEquals(fs.getFeatureCount(true), 1); // positional
+ assertEquals(fs.getFeatureCount(false), 1); // non-positional
+
+ /*
+ * add contact
+ */
+ SequenceFeature sf5 = new SequenceFeature("Disulfide bond", "", 0, 0,
+ Float.NaN, null);
+ assertTrue(fs.addFeature(sf5));
+ assertEquals(fs.getFeatureCount(true), 2); // positional - add 1 for contact
+ assertEquals(fs.getFeatureCount(false), 1); // non-positional
+ SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "", 0, 0,
+ Float.NaN, null);
+ assertFalse(fs.addFeature(sf6)); // already stored
+ assertEquals(fs.getFeatureCount(true), 2); // no change
+ assertEquals(fs.getFeatureCount(false), 1); // no change
}
@Test(groups = "Functional")
{
FeatureStore fs = new FeatureStore();
assertTrue(fs.isEmpty());
- assertEquals(fs.size(true), 0);
+ assertEquals(fs.getFeatureCount(true), 0);
/*
* non-nested feature
Float.NaN, null);
fs.addFeature(sf1);
assertFalse(fs.isEmpty());
- assertEquals(fs.size(true), 1);
+ assertEquals(fs.getFeatureCount(true), 1);
fs.delete(sf1);
assertTrue(fs.isEmpty());
- assertEquals(fs.size(true), 0);
+ assertEquals(fs.getFeatureCount(true), 0);
/*
* non-positional feature
sf1 = new SequenceFeature("Cath", "", 0, 0, Float.NaN, null);
fs.addFeature(sf1);
assertFalse(fs.isEmpty());
- assertEquals(fs.size(false), 1); // non-positional
- assertEquals(fs.size(true), 0); // positional
+ assertEquals(fs.getFeatureCount(false), 1); // non-positional
+ assertEquals(fs.getFeatureCount(true), 0); // positional
fs.delete(sf1);
assertTrue(fs.isEmpty());
- assertEquals(fs.size(false), 0);
+ assertEquals(fs.getFeatureCount(false), 0);
/*
* contact feature
sf1 = new SequenceFeature("Disulfide bond", "", 19, 49, Float.NaN, null);
fs.addFeature(sf1);
assertFalse(fs.isEmpty());
- assertEquals(fs.size(true), 1);
+ assertEquals(fs.getFeatureCount(true), 1);
fs.delete(sf1);
assertTrue(fs.isEmpty());
- assertEquals(fs.size(true), 0);
+ assertEquals(fs.getFeatureCount(true), 0);
/*
* sf2, sf3 added as nested features
fs.addFeature(sf1);
fs.addFeature(sf2);
fs.addFeature(sf3);
- assertEquals(fs.size(true), 3);
+ assertEquals(fs.getFeatureCount(true), 3);
assertTrue(fs.delete(sf1));
- assertEquals(fs.size(true), 2);
+ assertEquals(fs.getFeatureCount(true), 2);
// FeatureStore should now only contain features in the NCList
assertTrue(fs.nonNestedFeatures.isEmpty());
assertEquals(fs.nestedFeatures.size(), 2);
assertFalse(fs.isEmpty());
assertTrue(fs.delete(sf2));
- assertEquals(fs.size(true), 1);
+ assertEquals(fs.getFeatureCount(true), 1);
assertFalse(fs.isEmpty());
assertTrue(fs.delete(sf3));
- assertEquals(fs.size(true), 0);
+ assertEquals(fs.getFeatureCount(true), 0);
assertTrue(fs.isEmpty()); // all gone
}
}
@Test(groups = "Functional")
- public void testGetAverageFeatureLength()
+ public void testGetTotalFeatureLength()
{
FeatureStore fs = new FeatureStore();
- assertEquals(fs.getAverageFeatureLength(), 0f);
+ assertEquals(fs.getTotalFeatureLength(), 0);
addFeature(fs, 10, 20); // 11
- assertEquals(fs.getAverageFeatureLength(), 11f);
+ assertEquals(fs.getTotalFeatureLength(), 11);
addFeature(fs, 17, 37); // 21
addFeature(fs, 14, 74); // 61
- assertEquals(fs.getAverageFeatureLength(), 31f);
+ assertEquals(fs.getTotalFeatureLength(), 93);
// non-positional features don't count
SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 0, 0, 1f,
"group1");
fs.addFeature(sf1);
- assertEquals(fs.getAverageFeatureLength(), 31f);
+ assertEquals(fs.getTotalFeatureLength(), 93);
// contact features count 1
SequenceFeature sf2 = new SequenceFeature("disulphide bond", "desc",
15, 35, 1f, "group1");
fs.addFeature(sf2);
- assertEquals(fs.getAverageFeatureLength(), 94f / 4f);
+ assertEquals(fs.getTotalFeatureLength(), 94);
}
}
assertTrue(groups.contains("turn"));
assertTrue(groups.contains("strand"));
}
+
+ @Test(groups = "Functional")
+ public void testGetFeatureTypes()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+ Set<String> types = store.getFeatureTypes();
+ assertTrue(types.isEmpty());
+
+ SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf1);
+ types = store.getFeatureTypes();
+ assertEquals(types.size(), 1);
+ assertTrue(types.contains("Metal"));
+
+ // null type is possible...
+ SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf2);
+ types = store.getFeatureTypes();
+ assertEquals(types.size(), 2);
+ assertTrue(types.contains(null));
+ assertTrue(types.contains("Metal"));
+
+ /*
+ * add non-positional feature
+ */
+ SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+ Float.NaN, null);
+ store.add(sf3);
+ types = store.getFeatureTypes();
+ assertEquals(types.size(), 3);
+ assertTrue(types.contains("Pfam"));
+
+ /*
+ * add contact feature
+ */
+ SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+ 10, 20, Float.NaN, null);
+ store.add(sf4);
+ types = store.getFeatureTypes();
+ assertEquals(types.size(), 4);
+ assertTrue(types.contains("Disulphide Bond"));
+
+ /*
+ * add another Pfam
+ */
+ SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf5);
+ types = store.getFeatureTypes();
+ assertEquals(types.size(), 4); // unchanged
+
+ /*
+ * delete first Pfam - still have one
+ */
+ assertTrue(store.delete(sf3));
+ types = store.getFeatureTypes();
+ assertEquals(types.size(), 4);
+ assertTrue(types.contains("Pfam"));
+
+ /*
+ * delete second Pfam - no longer have one
+ */
+ assertTrue(store.delete(sf5));
+ types = store.getFeatureTypes();
+ assertEquals(types.size(), 3);
+ assertFalse(types.contains("Pfam"));
+ }
+
+ @Test(groups = "Functional")
+ public void testGetFeatureCount()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+ assertEquals(store.getFeatureCount(true), 0);
+ assertEquals(store.getFeatureCount(false), 0);
+
+ /*
+ * add positional
+ */
+ SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf1);
+ assertEquals(store.getFeatureCount(true), 1);
+ assertEquals(store.getFeatureCount(false), 0);
+
+ /*
+ * another positional
+ */
+ SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf2);
+ assertEquals(store.getFeatureCount(true), 2);
+ assertEquals(store.getFeatureCount(false), 0);
+
+ /*
+ * add non-positional feature
+ */
+ SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+ Float.NaN, null);
+ store.add(sf3);
+ assertEquals(store.getFeatureCount(true), 2);
+ assertEquals(store.getFeatureCount(false), 1);
+
+ /*
+ * add contact feature (counts as 1)
+ */
+ SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+ 10, 20, Float.NaN, null);
+ store.add(sf4);
+ assertEquals(store.getFeatureCount(true), 3);
+ assertEquals(store.getFeatureCount(false), 1);
+
+ /*
+ * add another Pfam
+ */
+ SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf5);
+ assertEquals(store.getFeatureCount(true), 4);
+ assertEquals(store.getFeatureCount(false), 1);
+ assertEquals(store.getFeatureCount(true, "Pfam"), 1);
+ assertEquals(store.getFeatureCount(false, "Pfam"), 1);
+ // search for type==null
+ assertEquals(store.getFeatureCount(true, (String) null), 1);
+ // search with no type specified
+ assertEquals(store.getFeatureCount(true, (String[]) null), 4);
+ assertEquals(store.getFeatureCount(true, "Metal", "Cath"), 1);
+ assertEquals(store.getFeatureCount(true, "Disulphide Bond"), 1);
+ assertEquals(store.getFeatureCount(true, "Metal", "Pfam", null), 3);
+
+ /*
+ * delete first Pfam (non-positional)
+ */
+ assertTrue(store.delete(sf3));
+ assertEquals(store.getFeatureCount(true), 4);
+ assertEquals(store.getFeatureCount(false), 0);
+
+ /*
+ * delete second Pfam (positional)
+ */
+ assertTrue(store.delete(sf5));
+ assertEquals(store.getFeatureCount(true), 3);
+ assertEquals(store.getFeatureCount(false), 0);
+ }
+
+ @Test(groups = "Functional")
+ public void testGetAllFeatures()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+ List<SequenceFeature> features = store.getAllFeatures();
+ assertTrue(features.isEmpty());
+
+ SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf1);
+ features = store.getAllFeatures();
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf1));
+
+ SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf2);
+ features = store.getAllFeatures();
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(sf2));
+
+ /*
+ * add non-positional feature
+ */
+ SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 0, 0,
+ Float.NaN, null);
+ store.add(sf3);
+ features = store.getAllFeatures();
+ assertEquals(features.size(), 3);
+ assertTrue(features.contains(sf3));
+
+ /*
+ * add contact feature
+ */
+ SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
+ 10, 20, Float.NaN, null);
+ store.add(sf4);
+ features = store.getAllFeatures();
+ assertEquals(features.size(), 4);
+ assertTrue(features.contains(sf4));
+
+ /*
+ * add another Pfam
+ */
+ SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf5);
+ features = store.getAllFeatures();
+ assertEquals(features.size(), 5);
+ assertTrue(features.contains(sf5));
+ features = store.getAllFeatures("Cath");
+ assertTrue(features.isEmpty());
+ features = store.getAllFeatures("Pfam", "Cath", "Metal");
+ assertEquals(features.size(), 3);
+ assertTrue(features.contains(sf1));
+ assertTrue(features.contains(sf3));
+ assertTrue(features.contains(sf5));
+
+ /*
+ * delete first Pfam
+ */
+ assertTrue(store.delete(sf3));
+ features = store.getAllFeatures();
+ assertEquals(features.size(), 4);
+ assertFalse(features.contains(sf3));
+
+ /*
+ * delete second Pfam
+ */
+ assertTrue(store.delete(sf5));
+ features = store.getAllFeatures();
+ assertEquals(features.size(), 3);
+ assertFalse(features.contains(sf3));
+ }
}