From 8f8c3ca7ac8630c75b76fcbab825444c5c672b86 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Tue, 11 Apr 2017 08:46:54 +0100 Subject: [PATCH] JAL-2446 added getFeatureGroups --- src/jalview/datamodel/features/FeatureStore.java | 59 +++++++++++++++++++- .../datamodel/features/SequenceFeatures.java | 18 ++++++ .../datamodel/features/FeatureStoreTest.java | 54 ++++++++++++++++++ .../datamodel/features/SequenceFeaturesTest.java | 46 +++++++++++++++ 4 files changed, 176 insertions(+), 1 deletion(-) diff --git a/src/jalview/datamodel/features/FeatureStore.java b/src/jalview/datamodel/features/FeatureStore.java index 4e70dda..6be33ef 100644 --- a/src/jalview/datamodel/features/FeatureStore.java +++ b/src/jalview/datamodel/features/FeatureStore.java @@ -5,7 +5,9 @@ import jalview.datamodel.SequenceFeature; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * A data store for a set of sequence features that supports efficient lookup of @@ -54,12 +56,20 @@ public class FeatureStore */ NCList nestedFeatures; + /* + * Feature groups represented in the stored features + * (possibly including null) + */ + Set featureGroups; + /** * Constructor */ public FeatureStore() { nonNestedFeatures = new ArrayList(); + featureGroups = new HashSet(); + // we only construct nonPositionalFeatures, contactFeatures // or the NCList if we need to } @@ -74,6 +84,8 @@ public class FeatureStore */ public boolean addFeature(SequenceFeature feature) { + featureGroups.add(feature.getFeatureGroup()); + boolean added = false; if (feature.isContactFeature()) @@ -572,7 +584,7 @@ public class FeatureStore * * @param sf */ - public boolean delete(SequenceFeature sf) + public synchronized boolean delete(SequenceFeature sf) { /* * try the non-nested positional features first @@ -608,10 +620,44 @@ public class FeatureStore removed = nestedFeatures.delete(sf); } + if (removed) + { + /* + * if this was the only feature for its feature group, + * remove the group from the stored set + */ + String featureGroup = sf.getFeatureGroup(); + if (!findFeatureGroup(featureGroup)) + { + featureGroups.remove(featureGroup); + } + } + return removed; } /** + * Scans all 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 : getFeatures()) + { + 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 @@ -627,4 +673,15 @@ public class FeatureStore return !hasFeatures; } + + /** + * Answers the set of distinct feature groups stored, possibly including null, + * as an unmodifiable view of the set. + * + * @return + */ + public Set getFeatureGroups() + { + return Collections.unmodifiableSet(featureGroups); + } } diff --git a/src/jalview/datamodel/features/SequenceFeatures.java b/src/jalview/datamodel/features/SequenceFeatures.java index 227d8fd..a61eff2 100644 --- a/src/jalview/datamodel/features/SequenceFeatures.java +++ b/src/jalview/datamodel/features/SequenceFeatures.java @@ -5,8 +5,10 @@ import jalview.datamodel.SequenceFeature; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; /** * A class that stores sequence features in a way that supports efficient @@ -207,4 +209,20 @@ public class SequenceFeatures } return false; } + + /** + * Returns a set of the distinct feature groups present in the collection. The + * set may include null. + * + * @return + */ + public Set getFeatureGroups() + { + Set groups = new HashSet(); + for (FeatureStore featureSet : featureStore.values()) + { + groups.addAll(featureSet.getFeatureGroups()); + } + return groups; + } } diff --git a/test/jalview/datamodel/features/FeatureStoreTest.java b/test/jalview/datamodel/features/FeatureStoreTest.java index 171b7c3..0945803 100644 --- a/test/jalview/datamodel/features/FeatureStoreTest.java +++ b/test/jalview/datamodel/features/FeatureStoreTest.java @@ -7,6 +7,7 @@ import static org.testng.Assert.assertTrue; import jalview.datamodel.SequenceFeature; import java.util.List; +import java.util.Set; import org.testng.annotations.Test; @@ -422,4 +423,57 @@ public class FeatureStoreTest assertTrue(fs.delete(sf3)); assertTrue(fs.isEmpty()); // all gone } + + @Test(groups = "Functional") + public void testGetFeatureGroups() + { + FeatureStore fs = new FeatureStore(); + assertTrue(fs.getFeatureGroups().isEmpty()); + + SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 10, 20, 1f, "group1"); + fs.addFeature(sf1); + Set groups = fs.getFeatureGroups(); + assertEquals(groups.size(), 1); + assertTrue(groups.contains("group1")); + + /* + * add another feature of the same group, delete one, delete both + */ + SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group1"); + fs.addFeature(sf2); + groups = fs.getFeatureGroups(); + assertEquals(groups.size(), 1); + assertTrue(groups.contains("group1")); + fs.delete(sf2); + groups = fs.getFeatureGroups(); + assertEquals(groups.size(), 1); + assertTrue(groups.contains("group1")); + fs.delete(sf1); + groups = fs.getFeatureGroups(); + assertTrue(fs.getFeatureGroups().isEmpty()); + + SequenceFeature sf3 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "group2"); + fs.addFeature(sf3); + SequenceFeature sf4 = new SequenceFeature("Cath", "desc", 20, 30, 1f, "Group2"); + fs.addFeature(sf4); + SequenceFeature sf5 = new SequenceFeature("Cath", "desc", 20, 30, 1f, null); + fs.addFeature(sf5); + groups = fs.getFeatureGroups(); + assertEquals(groups.size(), 3); + assertTrue(groups.contains("group2")); + assertTrue(groups.contains("Group2")); // case sensitive + assertTrue(groups.contains(null)); // null allowed + + fs.delete(sf3); + groups = fs.getFeatureGroups(); + assertEquals(groups.size(), 2); + assertFalse(groups.contains("group2")); + fs.delete(sf4); + groups = fs.getFeatureGroups(); + assertEquals(groups.size(), 1); + assertFalse(groups.contains("Group2")); + fs.delete(sf5); + groups = fs.getFeatureGroups(); + assertTrue(groups.isEmpty()); + } } diff --git a/test/jalview/datamodel/features/SequenceFeaturesTest.java b/test/jalview/datamodel/features/SequenceFeaturesTest.java index 1ee21f3..d5da9fa 100644 --- a/test/jalview/datamodel/features/SequenceFeaturesTest.java +++ b/test/jalview/datamodel/features/SequenceFeaturesTest.java @@ -7,6 +7,7 @@ import static org.testng.Assert.assertTrue; import jalview.datamodel.SequenceFeature; import java.util.List; +import java.util.Set; import org.testng.annotations.Test; @@ -310,4 +311,49 @@ public class SequenceFeaturesTest sf.delete(sf1); assertFalse(sf.hasFeatures()); } + + @Test(groups = "Functional") + public void testGetFeatureGroups() + { + SequenceFeatures sf = new SequenceFeatures(); + assertTrue(sf.getFeatureGroups().isEmpty()); + + SequenceFeature sf1 = new SequenceFeature("Pfam", "Desc", 10, 50, 0f, + "PfamGroup"); + sf.add(sf1); + Set groups = sf.getFeatureGroups(); + assertEquals(groups.size(), 1); + assertTrue(groups.contains("PfamGroup")); + + SequenceFeature sf2 = new SequenceFeature("Cath", "Desc", 10, 50, 0f, + null); + sf.add(sf2); + groups = sf.getFeatureGroups(); + assertEquals(groups.size(), 2); + assertTrue(groups.contains("PfamGroup")); + assertTrue(groups.contains(null)); + + sf.delete(sf1); + sf.delete(sf2); + assertTrue(sf.getFeatureGroups().isEmpty()); + + SequenceFeature sf3 = new SequenceFeature("CDS", "", 10, 50, 0f, + "Ensembl"); + sf.add(sf3); + SequenceFeature sf4 = new SequenceFeature("exon", "", 10, 50, 0f, + "Ensembl"); + sf.add(sf4); + groups = sf.getFeatureGroups(); + assertEquals(groups.size(), 1); + assertTrue(groups.contains("Ensembl")); + + /* + * delete last Ensembl group feature from CDS features + * but still have one in exon features + */ + sf.delete(sf3); + groups = sf.getFeatureGroups(); + assertEquals(groups.size(), 1); + assertTrue(groups.contains("Ensembl")); + } } -- 1.7.10.2