X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=test%2Fjalview%2Fdatamodel%2Ffeatures%2FSequenceFeaturesTest.java;h=7dde97b6006b5db39bf4b91115963de7efa3f37c;hb=3684934fd25c4941bd2d6ec8bc9dc7d760979f4e;hp=31703cd945a86a39e0f7d7854e9a8a544c13484c;hpb=661f8bc80f969f31d7aeceb9af7d01374c8e1f35;p=jalview.git
diff --git a/test/jalview/datamodel/features/SequenceFeaturesTest.java b/test/jalview/datamodel/features/SequenceFeaturesTest.java
index 31703cd..7dde97b 100644
--- a/test/jalview/datamodel/features/SequenceFeaturesTest.java
+++ b/test/jalview/datamodel/features/SequenceFeaturesTest.java
@@ -1,19 +1,75 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see .
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
package jalview.datamodel.features;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
-import jalview.datamodel.SequenceFeature;
-
+import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.testng.annotations.Test;
+import jalview.datamodel.SequenceFeature;
+import junit.extensions.PA;
+
public class SequenceFeaturesTest
{
@Test(groups = "Functional")
+ public void testConstructor()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+ assertFalse(store.hasFeatures());
+
+ store = new SequenceFeatures((List) null);
+ assertFalse(store.hasFeatures());
+
+ List features = new ArrayList<>();
+ store = new SequenceFeatures(features);
+ assertFalse(store.hasFeatures());
+
+ SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
+ Float.NaN, null);
+ features.add(sf1);
+ SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 15, 18,
+ Float.NaN, null);
+ features.add(sf2); // nested
+ SequenceFeature sf3 = new SequenceFeature("Pfam", "desc2", 0, 0,
+ Float.NaN, null); // non-positional
+ features.add(sf3);
+ store = new SequenceFeatures(features);
+ assertTrue(store.hasFeatures());
+ assertEquals(2, store.getFeatureCount(true)); // positional
+ assertEquals(1, store.getFeatureCount(false)); // non-positional
+ assertFalse(store.add(sf1)); // already contained
+ assertFalse(store.add(sf2)); // already contained
+ assertFalse(store.add(sf3)); // already contained
+ }
+
+ @Test(groups = "Functional")
public void testGetPositionalFeatures()
{
SequenceFeaturesI store = new SequenceFeatures();
@@ -41,8 +97,8 @@ public class SequenceFeaturesTest
Float.NaN, null);
store.add(sf6);
// contact feature
- SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
- 18, 45, Float.NaN, null);
+ SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc", 18,
+ 45, Float.NaN, null);
store.add(sf7);
// different feature type
SequenceFeature sf8 = new SequenceFeature("Pfam", "desc", 30, 40,
@@ -106,8 +162,8 @@ public class SequenceFeaturesTest
Float.NaN, null);
store.add(sf2);
// contact feature
- SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
- 18, 45, Float.NaN, null);
+ SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc", 18,
+ 45, Float.NaN, null);
store.add(sf3);
// repeat for different feature type
SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
@@ -119,7 +175,7 @@ public class SequenceFeaturesTest
SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
45, Float.NaN, null);
store.add(sf6);
-
+
/*
* get all contact features
*/
@@ -127,7 +183,7 @@ public class SequenceFeaturesTest
assertEquals(features.size(), 2);
assertTrue(features.contains(sf3));
assertTrue(features.contains(sf6));
-
+
/*
* get contact features by type
*/
@@ -135,11 +191,11 @@ public class SequenceFeaturesTest
assertTrue(store.getContactFeatures("Cath").isEmpty());
assertTrue(store.getContactFeatures("Pfam").isEmpty());
assertTrue(store.getContactFeatures("DISULPHIDE BOND").isEmpty());
-
+
features = store.getContactFeatures("Disulphide bond");
assertEquals(features.size(), 1);
assertTrue(features.contains(sf3));
-
+
features = store.getContactFeatures("Disulfide bond");
assertEquals(features.size(), 1);
assertTrue(features.contains(sf6));
@@ -158,8 +214,8 @@ public class SequenceFeaturesTest
Float.NaN, null);
store.add(sf2);
// contact feature
- SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
- 18, 45, Float.NaN, null);
+ SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc", 18,
+ 45, Float.NaN, null);
store.add(sf3);
// repeat for different feature type
SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
@@ -175,7 +231,7 @@ public class SequenceFeaturesTest
SequenceFeature sf7 = new SequenceFeature("Pfam", "desc2", 0, 0,
Float.NaN, null);
store.add(sf7);
-
+
/*
* get all non-positional features
*/
@@ -184,18 +240,18 @@ public class SequenceFeaturesTest
assertTrue(features.contains(sf2));
assertTrue(features.contains(sf5));
assertTrue(features.contains(sf7));
-
+
/*
* get non-positional features by type
*/
assertTrue(store.getNonPositionalFeatures((String) null).isEmpty());
assertTrue(store.getNonPositionalFeatures("Cath").isEmpty());
assertTrue(store.getNonPositionalFeatures("PFAM").isEmpty());
-
+
features = store.getNonPositionalFeatures("Metal");
assertEquals(features.size(), 1);
assertTrue(features.contains(sf2));
-
+
features = store.getNonPositionalFeatures("Pfam");
assertEquals(features.size(), 2);
assertTrue(features.contains(sf5));
@@ -214,8 +270,7 @@ public class SequenceFeaturesTest
SequenceFeature addFeature(SequenceFeaturesI sf, String type, int from,
int to)
{
- SequenceFeature sf1 = new SequenceFeature(type, "", from, to,
- Float.NaN,
+ SequenceFeature sf1 = new SequenceFeature(type, "", from, to, Float.NaN,
null);
sf.add(sf1);
return sf1;
@@ -237,33 +292,31 @@ public class SequenceFeaturesTest
SequenceFeature sf10 = addFeature(sf, "Cath", 40, 100);
SequenceFeature sf11 = addFeature(sf, "Cath", 60, 100);
SequenceFeature sf12 = addFeature(sf, "Cath", 70, 70);
- // null type is weird but possible:
- SequenceFeature sf13 = addFeature(sf, null, 5, 12);
-
+
List overlaps = sf.findFeatures(200, 200, "Pfam");
assertTrue(overlaps.isEmpty());
-
- overlaps = sf.findFeatures( 1, 9, "Pfam");
+
+ overlaps = sf.findFeatures(1, 9, "Pfam");
assertEquals(overlaps.size(), 1);
assertTrue(overlaps.contains(sf2));
-
- overlaps = sf.findFeatures( 5, 18, "Pfam");
+
+ overlaps = sf.findFeatures(5, 18, "Pfam");
assertEquals(overlaps.size(), 2);
assertTrue(overlaps.contains(sf1));
assertTrue(overlaps.contains(sf2));
-
+
overlaps = sf.findFeatures(30, 40, "Pfam");
assertEquals(overlaps.size(), 3);
assertTrue(overlaps.contains(sf1));
assertTrue(overlaps.contains(sf3));
assertTrue(overlaps.contains(sf4));
-
- overlaps = sf.findFeatures( 80, 90, "Pfam");
+
+ overlaps = sf.findFeatures(80, 90, "Pfam");
assertEquals(overlaps.size(), 2);
assertTrue(overlaps.contains(sf4));
assertTrue(overlaps.contains(sf5));
-
- overlaps = sf.findFeatures( 68, 70, "Pfam");
+
+ overlaps = sf.findFeatures(68, 70, "Pfam");
assertEquals(overlaps.size(), 3);
assertTrue(overlaps.contains(sf4));
assertTrue(overlaps.contains(sf5));
@@ -281,8 +334,7 @@ public class SequenceFeaturesTest
assertTrue(sf.findFeatures(0, 1000, "Metal").isEmpty());
overlaps = sf.findFeatures(7, 7, (String) null);
- assertEquals(overlaps.size(), 1);
- assertTrue(overlaps.contains(sf13));
+ assertTrue(overlaps.isEmpty());
}
@Test(groups = "Functional")
@@ -334,17 +386,20 @@ public class SequenceFeaturesTest
groups = sf.getFeatureGroups(false); // for non-positional
assertEquals(groups.size(), 1);
assertTrue(groups.contains("AGroup"));
+ groups = sf.getFeatureGroups(false, "AType");
+ assertEquals(groups.size(), 1);
+ assertTrue(groups.contains("AGroup"));
+ groups = sf.getFeatureGroups(true, "AnotherType");
+ assertTrue(groups.isEmpty());
/*
* add, then delete, more non-positional features of different types
*/
SequenceFeature sfy = new SequenceFeature("AnotherType", "Desc", 0, 0,
- 0f,
- "AnotherGroup");
+ 0f, "AnotherGroup");
sf.add(sfy);
SequenceFeature sfz = new SequenceFeature("AThirdType", "Desc", 0, 0,
- 0f,
- null);
+ 0f, null);
sf.add(sfz);
groups = sf.getFeatureGroups(false);
assertEquals(groups.size(), 3);
@@ -414,7 +469,7 @@ public class SequenceFeaturesTest
{
SequenceFeaturesI sf = new SequenceFeatures();
assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
-
+
/*
* add feature with group = "Uniprot", type = "helix"
*/
@@ -426,7 +481,7 @@ public class SequenceFeaturesTest
assertEquals(groups.size(), 1);
assertTrue(groups.contains("helix"));
assertTrue(sf.getFeatureTypesForGroups(true, (String) null).isEmpty());
-
+
/*
* add feature with group = "Uniprot", type = "strand"
*/
@@ -487,8 +542,9 @@ public class SequenceFeaturesTest
assertTrue(groups.contains("turn"));
assertTrue(groups.contains("strand"));
// alternative vararg syntax
- groups = sf.getFeatureTypesForGroups(true, new String[] { "Cath",
- "Scop" });
+ groups = sf.getFeatureTypesForGroups(true,
+ new String[]
+ { "Cath", "Scop" });
assertEquals(groups.size(), 2);
assertTrue(groups.contains("turn"));
assertTrue(groups.contains("strand"));
@@ -508,13 +564,13 @@ public class SequenceFeaturesTest
assertEquals(types.size(), 1);
assertTrue(types.contains("Metal"));
- // null type is possible...
+ // null type is rejected...
SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
Float.NaN, null);
- store.add(sf2);
+ assertFalse(store.add(sf2));
types = store.getFeatureTypes();
- assertEquals(types.size(), 2);
- assertTrue(types.contains(null));
+ assertEquals(types.size(), 1);
+ assertFalse(types.contains(null));
assertTrue(types.contains("Metal"));
/*
@@ -524,17 +580,17 @@ public class SequenceFeaturesTest
Float.NaN, null);
store.add(sf3);
types = store.getFeatureTypes();
- assertEquals(types.size(), 3);
+ assertEquals(types.size(), 2);
assertTrue(types.contains("Pfam"));
/*
* add contact feature
*/
- SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
- 10, 20, Float.NaN, null);
+ SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc", 10,
+ 20, Float.NaN, null);
store.add(sf4);
types = store.getFeatureTypes();
- assertEquals(types.size(), 4);
+ assertEquals(types.size(), 3);
assertTrue(types.contains("Disulphide Bond"));
/*
@@ -544,14 +600,14 @@ public class SequenceFeaturesTest
Float.NaN, null);
store.add(sf5);
types = store.getFeatureTypes();
- assertEquals(types.size(), 4); // unchanged
+ assertEquals(types.size(), 3); // unchanged
/*
* delete first Pfam - still have one
*/
assertTrue(store.delete(sf3));
types = store.getFeatureTypes();
- assertEquals(types.size(), 4);
+ assertEquals(types.size(), 3);
assertTrue(types.contains("Pfam"));
/*
@@ -559,7 +615,7 @@ public class SequenceFeaturesTest
*/
assertTrue(store.delete(sf5));
types = store.getFeatureTypes();
- assertEquals(types.size(), 3);
+ assertEquals(types.size(), 2);
assertFalse(types.contains("Pfam"));
}
@@ -569,7 +625,7 @@ public class SequenceFeaturesTest
SequenceFeaturesI store = new SequenceFeatures();
assertEquals(store.getFeatureCount(true), 0);
assertEquals(store.getFeatureCount(false), 0);
-
+
/*
* add positional
*/
@@ -580,62 +636,62 @@ public class SequenceFeaturesTest
assertEquals(store.getFeatureCount(false), 0);
/*
- * another positional
+ * null feature type is rejected
*/
SequenceFeature sf2 = new SequenceFeature(null, "desc", 10, 20,
Float.NaN, null);
- store.add(sf2);
- assertEquals(store.getFeatureCount(true), 2);
+ assertFalse(store.add(sf2));
+ assertEquals(store.getFeatureCount(true), 1);
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(true), 1);
assertEquals(store.getFeatureCount(false), 1);
-
+
/*
* add contact feature (counts as 1)
*/
- SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
- 10, 20, Float.NaN, null);
+ SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc", 10,
+ 20, Float.NaN, null);
store.add(sf4);
- assertEquals(store.getFeatureCount(true), 3);
+ assertEquals(store.getFeatureCount(true), 2);
assertEquals(store.getFeatureCount(false), 1);
-
+
/*
- * add another Pfam
+ * add another Pfam but this time as a positional feature
*/
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);
+ assertEquals(store.getFeatureCount(true), 3); // sf1, sf4, sf5
+ assertEquals(store.getFeatureCount(false), 1); // sf3
+ assertEquals(store.getFeatureCount(true, "Pfam"), 1); // positional
+ assertEquals(store.getFeatureCount(false, "Pfam"), 1); // non-positional
// search for type==null
- assertEquals(store.getFeatureCount(true, (String) null), 1);
+ assertEquals(store.getFeatureCount(true, (String) null), 0);
// search with no type specified
- assertEquals(store.getFeatureCount(true, (String[]) null), 4);
+ assertEquals(store.getFeatureCount(true, (String[]) null), 3);
assertEquals(store.getFeatureCount(true, "Metal", "Cath"), 1);
assertEquals(store.getFeatureCount(true, "Disulphide Bond"), 1);
- assertEquals(store.getFeatureCount(true, "Metal", "Pfam", null), 3);
+ assertEquals(store.getFeatureCount(true, "Metal", "Pfam", null), 2);
/*
* delete first Pfam (non-positional)
*/
assertTrue(store.delete(sf3));
- assertEquals(store.getFeatureCount(true), 4);
+ assertEquals(store.getFeatureCount(true), 3);
assertEquals(store.getFeatureCount(false), 0);
-
+
/*
* delete second Pfam (positional)
*/
assertTrue(store.delete(sf5));
- assertEquals(store.getFeatureCount(true), 3);
+ assertEquals(store.getFeatureCount(true), 2);
assertEquals(store.getFeatureCount(false), 0);
}
@@ -645,21 +701,21 @@ public class SequenceFeaturesTest
SequenceFeaturesI store = new SequenceFeatures();
List 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,
+
+ SequenceFeature sf2 = new SequenceFeature("Metallic", "desc", 10, 20,
Float.NaN, null);
store.add(sf2);
features = store.getAllFeatures();
assertEquals(features.size(), 2);
assertTrue(features.contains(sf2));
-
+
/*
* add non-positional feature
*/
@@ -669,17 +725,17 @@ public class SequenceFeaturesTest
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);
+ 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
*/
@@ -689,14 +745,20 @@ public class SequenceFeaturesTest
features = store.getAllFeatures();
assertEquals(features.size(), 5);
assertTrue(features.contains(sf5));
+
+ /*
+ * select by type does not apply to non-positional features
+ */
features = store.getAllFeatures("Cath");
- assertTrue(features.isEmpty());
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf3));
+
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
*/
@@ -704,7 +766,7 @@ public class SequenceFeaturesTest
features = store.getAllFeatures();
assertEquals(features.size(), 4);
assertFalse(features.contains(sf3));
-
+
/*
* delete second Pfam
*/
@@ -724,6 +786,8 @@ public class SequenceFeaturesTest
Float.NaN, null);
assertTrue(store.add(sf1));
assertEquals(store.getTotalFeatureLength(), 11);
+ assertEquals(store.getTotalFeatureLength("Metal"), 11);
+ assertEquals(store.getTotalFeatureLength("Plastic"), 0);
// re-add does nothing!
assertFalse(store.add(sf1));
@@ -740,8 +804,8 @@ public class SequenceFeaturesTest
/*
* add contact feature - counts 1 to feature length
*/
- SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc",
- 10, 20, Float.NaN, null);
+ SequenceFeature sf4 = new SequenceFeature("Disulphide Bond", "desc", 10,
+ 20, Float.NaN, null);
store.add(sf4);
assertEquals(store.getTotalFeatureLength(), 12);
@@ -768,4 +832,481 @@ public class SequenceFeaturesTest
assertTrue(store.delete(sf1));
assertEquals(store.getTotalFeatureLength(), 0);
}
+
+ @Test(groups = "Functional")
+ public void testGetMinimumScore_getMaximumScore()
+ {
+ SequenceFeatures sf = new SequenceFeatures();
+ SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 0, 0,
+ Float.NaN, "group"); // non-positional, no score
+ sf.add(sf1);
+ SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 10, 20,
+ Float.NaN, "group"); // positional, no score
+ sf.add(sf2);
+ SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 10, 20, 1f,
+ "group");
+ sf.add(sf3);
+ SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 12, 16, 4f,
+ "group");
+ sf.add(sf4);
+ SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 0, 0, 11f,
+ "group");
+ sf.add(sf5);
+ SequenceFeature sf6 = new SequenceFeature("Cath", "desc", 0, 0, -7f,
+ "group");
+ sf.add(sf6);
+
+ assertEquals(sf.getMinimumScore("nosuchtype", true), Float.NaN);
+ assertEquals(sf.getMinimumScore("nosuchtype", false), Float.NaN);
+ assertEquals(sf.getMaximumScore("nosuchtype", true), Float.NaN);
+ assertEquals(sf.getMaximumScore("nosuchtype", false), Float.NaN);
+
+ // positional features min-max:
+ assertEquals(sf.getMinimumScore("Metal", true), 1f);
+ assertEquals(sf.getMaximumScore("Metal", true), 4f);
+ assertEquals(sf.getMinimumScore("Cath", true), Float.NaN);
+ assertEquals(sf.getMaximumScore("Cath", true), Float.NaN);
+
+ // non-positional features min-max:
+ assertEquals(sf.getMinimumScore("Cath", false), -7f);
+ assertEquals(sf.getMaximumScore("Cath", false), 11f);
+ assertEquals(sf.getMinimumScore("Metal", false), Float.NaN);
+ assertEquals(sf.getMaximumScore("Metal", false), Float.NaN);
+
+ // delete features; min-max should get recomputed
+ sf.delete(sf6);
+ assertEquals(sf.getMinimumScore("Cath", false), 11f);
+ assertEquals(sf.getMaximumScore("Cath", false), 11f);
+ sf.delete(sf4);
+ assertEquals(sf.getMinimumScore("Metal", true), 1f);
+ assertEquals(sf.getMaximumScore("Metal", true), 1f);
+ sf.delete(sf5);
+ assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
+ assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
+ sf.delete(sf3);
+ assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
+ assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
+ sf.delete(sf1);
+ sf.delete(sf2);
+ assertFalse(sf.hasFeatures());
+ assertEquals(sf.getMinimumScore("Cath", false), Float.NaN);
+ assertEquals(sf.getMaximumScore("Cath", false), Float.NaN);
+ assertEquals(sf.getMinimumScore("Metal", true), Float.NaN);
+ assertEquals(sf.getMaximumScore("Metal", true), Float.NaN);
+ }
+
+ @Test(groups = "Functional")
+ public void testVarargsToTypes()
+ {
+ SequenceFeatures sf = new SequenceFeatures();
+ sf.add(new SequenceFeature("Metal", "desc", 0, 0, Float.NaN, "group"));
+ sf.add(new SequenceFeature("Cath", "desc", 10, 20, Float.NaN, "group"));
+
+ /*
+ * no type specified - get all types stored
+ * they are returned in keyset (alphabetical) order
+ */
+ Map featureStores = (Map) PA
+ .getValue(sf, "featureStore");
+
+ Iterable types = sf.varargToTypes();
+ Iterator iterator = types.iterator();
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Cath"));
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Metal"));
+ assertFalse(iterator.hasNext());
+
+ /*
+ * empty array is the same as no vararg parameter supplied
+ * so treated as all stored types
+ */
+ types = sf.varargToTypes(new String[] {});
+ iterator = types.iterator();
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Cath"));
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Metal"));
+ assertFalse(iterator.hasNext());
+
+ /*
+ * null type specified; this is passed as vararg
+ * String[1] {null}
+ */
+ types = sf.varargToTypes((String) null);
+ assertFalse(types.iterator().hasNext());
+
+ /*
+ * null types array specified; this is passed as vararg null
+ */
+ types = sf.varargToTypes((String[]) null);
+ iterator = types.iterator();
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Cath"));
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Metal"));
+ assertFalse(iterator.hasNext());
+
+ /*
+ * one type specified
+ */
+ types = sf.varargToTypes("Metal");
+ iterator = types.iterator();
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Metal"));
+ assertFalse(iterator.hasNext());
+
+ /*
+ * two types specified - order is preserved
+ */
+ types = sf.varargToTypes("Metal", "Cath");
+ iterator = types.iterator();
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Metal"));
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Cath"));
+ assertFalse(iterator.hasNext());
+
+ /*
+ * null type included - should be ignored
+ */
+ types = sf.varargToTypes("Metal", null, "Helix");
+ iterator = types.iterator();
+ assertTrue(iterator.hasNext());
+ assertSame(iterator.next(), featureStores.get("Metal"));
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test(groups = "Functional")
+ public void testGetFeatureTypes_byOntology()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+
+ SequenceFeature sf1 = new SequenceFeature("transcript", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf1);
+ // mRNA isA mature_transcript isA transcript
+ SequenceFeature sf2 = new SequenceFeature("mRNA", "desc", 10, 20,
+ Float.NaN, null);
+ store.add(sf2);
+ // just to prove non-positional feature types are included
+ SequenceFeature sf3 = new SequenceFeature("mRNA", "desc", 0, 0,
+ Float.NaN, null);
+ store.add(sf3);
+ SequenceFeature sf4 = new SequenceFeature("CDS", "desc", 0, 0,
+ Float.NaN, null);
+ store.add(sf4);
+
+ Set types = store.getFeatureTypes("transcript");
+ assertEquals(types.size(), 2);
+ assertTrue(types.contains("transcript"));
+ assertTrue(types.contains("mRNA"));
+
+ // matches include arguments whether SO terms or not
+ types = store.getFeatureTypes("transcript", "CDS");
+ assertEquals(types.size(), 3);
+ assertTrue(types.contains("transcript"));
+ assertTrue(types.contains("mRNA"));
+ assertTrue(types.contains("CDS"));
+
+ types = store.getFeatureTypes("exon");
+ assertTrue(types.isEmpty());
+ }
+
+ @Test(groups = "Functional")
+ public void testGetFeaturesByOntology()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+ List features = store.getFeaturesByOntology();
+ assertTrue(features.isEmpty());
+ assertTrue(store.getFeaturesByOntology(new String[] {}).isEmpty());
+ assertTrue(store.getFeaturesByOntology((String[]) null).isEmpty());
+
+ SequenceFeature transcriptFeature = new SequenceFeature("transcript",
+ "desc", 10, 20, Float.NaN, null);
+ store.add(transcriptFeature);
+
+ /*
+ * mRNA is a sub-type of transcript; added here 'as if' non-positional
+ * just to show that non-positional features are included in results
+ */
+ SequenceFeature mrnaFeature = new SequenceFeature("mRNA", "desc", 0, 0,
+ Float.NaN, null);
+ store.add(mrnaFeature);
+
+ SequenceFeature pfamFeature = new SequenceFeature("Pfam", "desc", 30,
+ 40, Float.NaN, null);
+ store.add(pfamFeature);
+
+ /*
+ * "transcript" matches both itself and the sub-term "mRNA"
+ */
+ features = store.getFeaturesByOntology("transcript");
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(transcriptFeature));
+ assertTrue(features.contains(mrnaFeature));
+
+ /*
+ * "mRNA" matches itself but not parent term "transcript"
+ */
+ features = store.getFeaturesByOntology("mRNA");
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(mrnaFeature));
+
+ /*
+ * "pfam" is not an SO term but is included as an exact match
+ */
+ features = store.getFeaturesByOntology("mRNA", "Pfam");
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(mrnaFeature));
+ assertTrue(features.contains(pfamFeature));
+
+ features = store.getFeaturesByOntology("sequence_variant");
+ assertTrue(features.isEmpty());
+ }
+
+ @Test(groups = "Functional")
+ public void testSortFeatures()
+ {
+ List sfs = new ArrayList<>();
+ SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 30, 60,
+ Float.NaN, null);
+ sfs.add(sf1);
+ SequenceFeature sf2 = new SequenceFeature("Rfam", "desc", 40, 50,
+ Float.NaN, null);
+ sfs.add(sf2);
+ SequenceFeature sf3 = new SequenceFeature("Rfam", "desc", 50, 60,
+ Float.NaN, null);
+ sfs.add(sf3);
+ SequenceFeature sf4 = new SequenceFeature("Xfam", "desc", 30, 80,
+ Float.NaN, null);
+ sfs.add(sf4);
+ SequenceFeature sf5 = new SequenceFeature("Xfam", "desc", 30, 90,
+ Float.NaN, null);
+ sfs.add(sf5);
+
+ /*
+ * sort by end position descending, order unchanged if matched
+ */
+ SequenceFeatures.sortFeatures(sfs, false);
+ assertSame(sfs.get(0), sf5); // end 90
+ assertSame(sfs.get(1), sf4); // end 80
+ assertSame(sfs.get(2), sf1); // end 60, start 50
+ assertSame(sfs.get(3), sf3); // end 60, start 30
+ assertSame(sfs.get(4), sf2); // end 50
+
+ /*
+ * resort {5, 4, 1, 3, 2} by start position ascending, end descending
+ */
+ SequenceFeatures.sortFeatures(sfs, true);
+ assertSame(sfs.get(0), sf5); // start 30, end 90
+ assertSame(sfs.get(1), sf4); // start 30, end 80
+ assertSame(sfs.get(2), sf1); // start 30, end 60
+ assertSame(sfs.get(3), sf2); // start 40
+ assertSame(sfs.get(4), sf3); // start 50
+ }
+
+ @Test(groups = "Functional")
+ public void testGetFeaturesForGroup()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+
+ List features = store.getFeaturesForGroup(true, null);
+ assertTrue(features.isEmpty());
+ assertTrue(store.getFeaturesForGroup(false, null).isEmpty());
+ assertTrue(store.getFeaturesForGroup(true, "Uniprot").isEmpty());
+ assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
+
+ SequenceFeature sf1 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
+ null);
+ SequenceFeature sf2 = new SequenceFeature("Pfam", "desc", 0, 0, 0f,
+ null);
+ SequenceFeature sf3 = new SequenceFeature("Pfam", "desc", 4, 10, 0f,
+ "Uniprot");
+ SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 0, 0, 0f,
+ "Rfam");
+ SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 5, 15, 0f,
+ null);
+ store.add(sf1);
+ store.add(sf2);
+ store.add(sf3);
+ store.add(sf4);
+ store.add(sf5);
+
+ // positional features for null group, any type
+ features = store.getFeaturesForGroup(true, null);
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(sf1));
+ assertTrue(features.contains(sf5));
+
+ // positional features for null group, specified type
+ features = store.getFeaturesForGroup(true, null,
+ new String[]
+ { "Pfam", "Xfam" });
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf1));
+ features = store.getFeaturesForGroup(true, null,
+ new String[]
+ { "Pfam", "Xfam", "Cath" });
+ assertEquals(features.size(), 2);
+ assertTrue(features.contains(sf1));
+ assertTrue(features.contains(sf5));
+
+ // positional features for non-null group, any type
+ features = store.getFeaturesForGroup(true, "Uniprot");
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf3));
+ assertTrue(store.getFeaturesForGroup(true, "Rfam").isEmpty());
+
+ // positional features for non-null group, specified type
+ features = store.getFeaturesForGroup(true, "Uniprot", "Pfam", "Xfam",
+ "Rfam");
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf3));
+ assertTrue(
+ store.getFeaturesForGroup(true, "Uniprot", "Cath").isEmpty());
+
+ // non-positional features for null group, any type
+ features = store.getFeaturesForGroup(false, null);
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf2));
+
+ // non-positional features for null group, specified type
+ features = store.getFeaturesForGroup(false, null, "Pfam", "Xfam");
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf2));
+ assertTrue(store.getFeaturesForGroup(false, null, "Cath").isEmpty());
+
+ // non-positional features for non-null group, any type
+ features = store.getFeaturesForGroup(false, "Rfam");
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf4));
+ assertTrue(store.getFeaturesForGroup(false, "Uniprot").isEmpty());
+
+ // non-positional features for non-null group, specified type
+ features = store.getFeaturesForGroup(false, "Rfam", "Pfam", "Metal");
+ assertEquals(features.size(), 1);
+ assertTrue(features.contains(sf4));
+ assertTrue(store.getFeaturesForGroup(false, "Rfam", "Cath", "Pfam")
+ .isEmpty());
+ }
+
+ @Test(groups = "Functional")
+ public void testShiftFeatures()
+ {
+ SequenceFeatures store = new SequenceFeatures();
+ assertFalse(store.shiftFeatures(0, 1));
+
+ SequenceFeature sf1 = new SequenceFeature("Cath", "", 2, 5, 0f, null);
+ store.add(sf1);
+ // nested feature:
+ SequenceFeature sf2 = new SequenceFeature("Metal", "", 8, 14, 0f, null);
+ store.add(sf2);
+ // contact feature:
+ SequenceFeature sf3 = new SequenceFeature("Disulfide bond", "", 23, 32,
+ 0f, null);
+ store.add(sf3);
+ // non-positional feature:
+ SequenceFeature sf4 = new SequenceFeature("Pfam", "", 0, 0, 0f, null);
+ store.add(sf4);
+
+ /*
+ * shift features right by 5
+ */
+ assertTrue(store.shiftFeatures(0, 5));
+
+ // non-positional features untouched:
+ List nonPos = store.getNonPositionalFeatures();
+ assertEquals(nonPos.size(), 1);
+ assertTrue(nonPos.contains(sf4));
+
+ // positional features are replaced
+ List pos = store.getPositionalFeatures();
+ assertEquals(pos.size(), 3);
+ assertFalse(pos.contains(sf1));
+ assertFalse(pos.contains(sf2));
+ assertFalse(pos.contains(sf3));
+ SequenceFeatures.sortFeatures(pos, true); // ascending start pos
+ assertEquals(pos.get(0).getBegin(), 7);
+ assertEquals(pos.get(0).getEnd(), 10);
+ assertEquals(pos.get(0).getType(), "Cath");
+ assertEquals(pos.get(1).getBegin(), 13);
+ assertEquals(pos.get(1).getEnd(), 19);
+ assertEquals(pos.get(1).getType(), "Metal");
+ assertEquals(pos.get(2).getBegin(), 28);
+ assertEquals(pos.get(2).getEnd(), 37);
+ assertEquals(pos.get(2).getType(), "Disulfide bond");
+
+ /*
+ * now shift left by 15
+ * feature at [7-10] should be removed
+ * feature at [13-19] should become [1-4]
+ */
+ assertTrue(store.shiftFeatures(0, -15));
+ pos = store.getPositionalFeatures();
+ assertEquals(pos.size(), 2);
+ SequenceFeatures.sortFeatures(pos, true);
+ assertEquals(pos.get(0).getBegin(), 1);
+ assertEquals(pos.get(0).getEnd(), 4);
+ assertEquals(pos.get(0).getType(), "Metal");
+ assertEquals(pos.get(1).getBegin(), 13);
+ assertEquals(pos.get(1).getEnd(), 22);
+ assertEquals(pos.get(1).getType(), "Disulfide bond");
+
+ /*
+ * shift right by 4 from column 2
+ * feature at [1-4] should be unchanged
+ * feature at [13-22] should become [17-26]
+ */
+ assertTrue(store.shiftFeatures(2, 4));
+ pos = store.getPositionalFeatures();
+ assertEquals(pos.size(), 2);
+ SequenceFeatures.sortFeatures(pos, true);
+ assertEquals(pos.get(0).getBegin(), 1);
+ assertEquals(pos.get(0).getEnd(), 4);
+ assertEquals(pos.get(0).getType(), "Metal");
+ assertEquals(pos.get(1).getBegin(), 17);
+ assertEquals(pos.get(1).getEnd(), 26);
+ assertEquals(pos.get(1).getType(), "Disulfide bond");
+
+ /*
+ * shift right from column 18
+ * should be no updates
+ */
+ SequenceFeature f1 = pos.get(0);
+ SequenceFeature f2 = pos.get(1);
+ assertFalse(store.shiftFeatures(18, 6));
+ pos = store.getPositionalFeatures();
+ assertEquals(pos.size(), 2);
+ SequenceFeatures.sortFeatures(pos, true);
+ assertSame(pos.get(0), f1);
+ assertSame(pos.get(1), f2);
+ }
+
+ @Test(groups = "Functional")
+ public void testIsOntologyTerm()
+ {
+ SequenceFeatures store = new SequenceFeatures();
+ assertTrue(store.isOntologyTerm("gobbledygook"));
+ assertTrue(store.isOntologyTerm("transcript", "transcript"));
+ assertTrue(store.isOntologyTerm("mRNA", "transcript"));
+ assertFalse(store.isOntologyTerm("transcript", "mRNA"));
+ assertTrue(store.isOntologyTerm("junk", "transcript", "junk"));
+ assertTrue(store.isOntologyTerm("junk", new String[] {}));
+ assertTrue(store.isOntologyTerm("junk", (String[]) null));
+ }
+
+ @Test(groups = "Functional")
+ public void testDeleteAll()
+ {
+ SequenceFeaturesI store = new SequenceFeatures();
+ assertFalse(store.hasFeatures());
+ store.deleteAll();
+ assertFalse(store.hasFeatures());
+ store.add(new SequenceFeature("Cath", "Desc", 12, 20, 0f, "Group"));
+ store.add(new SequenceFeature("Pfam", "Desc", 6, 12, 2f, "Group2"));
+ assertTrue(store.hasFeatures());
+ store.deleteAll();
+ assertFalse(store.hasFeatures());
+ }
}