X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fext%2Fso%2FSequenceOntology.java;h=8a3805d1fb49c5c346274e4f215d6f14979edded;hb=9fcb12165750b20f8a73d0bb976b22be5fda94a2;hp=0d631e66ee3ed0c3124eb5f69f63d8a5f521f5f0;hpb=3d0101179759ef157b088ea135423cd909512d9f;p=jalview.git diff --git a/src/jalview/ext/so/SequenceOntology.java b/src/jalview/ext/so/SequenceOntology.java index 0d631e6..8a3805d 100644 --- a/src/jalview/ext/so/SequenceOntology.java +++ b/src/jalview/ext/so/SequenceOntology.java @@ -20,6 +20,7 @@ */ package jalview.ext.so; +import jalview.datamodel.ontology.OntologyBase; import jalview.io.gff.SequenceOntologyI; import java.io.BufferedInputStream; @@ -34,6 +35,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -48,7 +50,8 @@ import org.biojava.nbio.ontology.utils.Annotation; * A wrapper class that parses the Sequence Ontology and exposes useful access * methods. This version uses the BioJava parser. */ -public class SequenceOntology implements SequenceOntologyI +public class SequenceOntology extends OntologyBase + implements SequenceOntologyI { /* * the parsed Ontology data as modelled by BioJava @@ -82,10 +85,10 @@ public class SequenceOntology implements SequenceOntologyI */ public SequenceOntology() { - termsFound = new ArrayList(); - termsNotFound = new ArrayList(); - termsByDescription = new HashMap(); - termIsA = new HashMap>(); + termsFound = new ArrayList<>(); + termsNotFound = new ArrayList<>(); + termsByDescription = new HashMap<>(); + termIsA = new HashMap<>(); loadOntologyZipFile("so-xp-simple.obo"); } @@ -404,7 +407,7 @@ public class SequenceOntology implements SequenceOntologyI */ protected synchronized void findParents(Term childTerm) { - List result = new ArrayList(); + List result = new ArrayList<>(); for (Triple triple : ontology.getTriples(childTerm, null, isA)) { Term parent = triple.getObject(); @@ -471,4 +474,82 @@ public class SequenceOntology implements SequenceOntologyI return termsNotFound; } } + + /** + * {@inheritDoc} + * + * @throws IllegalStateException + * if a loop is detected in the ontology + */ + @Override + public List getRootParents(final String term) + { + /* + * check in cache first + */ + if (rootParents.containsKey(term)) + { + return rootParents.get(term); + } + Term t = getTerm(term); + if (t == null) + { + return null; + } + + /* + * todo: check for loops using 'seen', allowing for alternate paths e.g. + * stop_gained isA feature_truncation isA feature_variant + * " isA nonsynonymous_variant ... isA geneVariant isA feature_variant + */ + List seen = new ArrayList<>(); + List top = new ArrayList<>(); + List query = new ArrayList<>(); + query.add(t); + + while (!query.isEmpty()) + { + List nextQuery = new ArrayList<>(); + for (Term q : query) + { + Set parents = ontology.getTriples(q, null, isA); + if (parents.isEmpty()) + { + /* + * q has no parents so is a top level term + */ + top.add(q); + } + else + { + /* + * search all parent terms + */ + for (Triple triple : parents) + { + Term parent = triple.getObject(); + nextQuery.add(parent); + } + } + } + query = nextQuery; + } + + List result = new ArrayList<>(); + for (Term found : top) + { + String desc = found.getDescription(); + if (!result.contains(desc)) + { + result.add(desc); + } + } + + /* + * save result in cache + */ + rootParents.put(term, result); + + return result; + } }