diff --git a/ontolib-core/src/main/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntology.java b/ontolib-core/src/main/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntology.java index cd2559b..122f7e4 100644 --- a/ontolib-core/src/main/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntology.java +++ b/ontolib-core/src/main/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntology.java @@ -1,9 +1,6 @@ package com.github.phenomics.ontolib.ontology.data; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import com.github.phenomics.ontolib.graph.algo.BreadthFirstSearch; import com.github.phenomics.ontolib.graph.algo.VertexVisitor; @@ -193,9 +190,33 @@ public Ontology subOntology(TermId subOntologyRoot) { final Set childTermIds = OntologyTerms.childrenOf(subOntologyRoot, this); final ImmutableDirectedGraph> subGraph = (ImmutableDirectedGraph>) graph.subGraph(childTermIds); - return new ImmutableOntology(metaInfo, subGraph, subOntologyRoot, - Sets.intersection(nonObsoleteTermIds, childTermIds), - Sets.intersection(obsoleteTermIds, childTermIds), termMap, relationMap); + Set intersectingTerms = Sets.intersection(nonObsoleteTermIds,childTermIds); + // make sure the Term map contains only terms from the subontology + final ImmutableMap.Builder termBuilder = ImmutableMap.builder(); + + for (final TermId tid : intersectingTerms) { + termBuilder.put(tid,termMap.get(tid)); + } + ImmutableMap subsetTermMap=termBuilder.build(); + // Only retain relations where both source and destination are terms in the subontology + final ImmutableMap.Builder relationBuilder = ImmutableMap.builder(); + for(Iterator> it = relationMap.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = it.next(); + TermRelation tr = entry.getValue(); + if (subsetTermMap.containsKey(tr.getSource()) && subsetTermMap.containsKey(tr.getDest())) { + relationBuilder.put(entry.getKey(),entry.getValue()); + } + } + // Note: natural order returns a builder whose keys are ordered by their natural ordering. + final ImmutableSortedMap.Builder metaInfoBuilder = ImmutableSortedMap.naturalOrder(); + for (String key : metaInfo.keySet()) { + metaInfoBuilder.put(key,metaInfo.get(key)); + } + metaInfoBuilder.put("provenance",String.format("Ontology created as a subset from original ontology with root %s",getTermMap().get(rootTermId).getName() )); + ImmutableSortedMap extendedMetaInfo=metaInfoBuilder.build(); + + return new ImmutableOntology(extendedMetaInfo, subGraph, subOntologyRoot,intersectingTerms, + Sets.intersection(obsoleteTermIds, childTermIds), subsetTermMap, relationBuilder.build()); } } diff --git a/ontolib-core/src/test/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntologyTest.java b/ontolib-core/src/test/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntologyTest.java index 28aa8f6..4eb0a41 100644 --- a/ontolib-core/src/test/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntologyTest.java +++ b/ontolib-core/src/test/java/com/github/phenomics/ontolib/ontology/data/ImmutableOntologyTest.java @@ -2,9 +2,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; import org.junit.Test; +import java.util.Map; + public class ImmutableOntologyTest extends ImmutableOntologyTestBase { @Test @@ -36,4 +39,43 @@ public void test() { ontology.getParentTermIds(id1).toString()); } + /** + * The subontology defined by Term with id4 should consist of only the terms id4 and id1. + * The termmap should thus contain only two terms. The subontology does not contain the original root of the ontology, id5. + */ + @Test + public void testSubontologyCreation() { + ImmutableOntology subontology=(ImmutableOntology)ontology.subOntology(id4); + assertTrue(subontology.getTermMap().containsKey(id4)); + assertTrue(subontology.getTermMap().containsKey(id1)); + assertTrue(ontology.getTermMap().size()==5); + assertTrue(subontology.getTermMap().size()==2); + assertFalse(subontology.getTermMap().containsKey(id5)); + } + + /** + * The parent ontology has six relations + * 1 TestTermRelation [source=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000001], dest=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000002], id=1] + 2 TestTermRelation [source=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000001], dest=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000003], id=2] + 3 TestTermRelation [source=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000001], dest=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000004], id=3] + 4 TestTermRelation [source=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000002], dest=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000005], id=4] + 5 TestTermRelation [source=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000003], dest=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000005], id=5] + 6 TestTermRelation [source=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000004], dest=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000005], id=6] + The subontology has just the terms id1 and id4, and thus should just have only one relation./subontology + 3 TestTermRelation [source=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000001], dest=ImmutableTermId [prefix=ImmutableTermPrefix [value=HP], id=0000004], id=3] + */ + @Test + public void testSubontologyRelations() { + ImmutableOntology subontology=(ImmutableOntology)ontology.subOntology(id4); + Map relationMap = ontology.getRelationMap(); + int expectedSize=6; + assertEquals(expectedSize,relationMap.size()); + relationMap = subontology.getRelationMap(); + expectedSize=1; + assertEquals(expectedSize,relationMap.size()); + } + + + + }