Finally, working with bio-ontologies in Java is as easy as it should be
I'm a big fan of the OWL API. I've been using it for years to do useful things with OWL ontologies in Java. It's a comprehensive and powerful reference library for working with all aspects of the OWL language, and the repository also includes implementations for several experimental language extensions, such as the description graphs that we used to represent chemicals in our 2010 OWLED paper.
The problem is, the library is comprehensive, powerful, beautifully engineered... and has been inexplicably reported to be extremely difficult for software beginners or part-time-scripters-who-really-just-need-to-write-some-code-as-a-small-part-of-a-bigger-more-interesting-project to pick up.
The OWLTools project is designed to come to the rescue for Java programmers working with standard features of bio-ontologies in both OWL and OBO. Under the lead of Chris Mungall from the Gene Ontology Consortium, it has been developed as a volunteer effort bringing together convenience methods developed in the context of several bio-ontology engineering efforts. The result provides a comprehensive suite of simple, easy-to-use functions and classes that do useful things with ontologies in very few, easily readable, lines of code.
In what follows I will describe some of the features. Disclaimer: I'm not a developer of this library, just a fan -- it's probably best to go to the authors if you have questions. The purpose of this post is to highlight how neat and useful the OWLTools library is, not to bash the OWL API for being more complex: behind the scenes, it's still the OWL API is doing all the work.
1. Loading ontologies, retrieving their content
To load an ontology that is in either OBO or OWL format, it takes only a few short lines of code (for brevity, the extracts below omit essential Java stuff such as imports, class declarations, exception handling and so on):
String ontologyIRI="http://www.myontology.online/ontology.owl"; ParserWrapper pw = new ParserWrapper(); OWLGraphWrapper g = pw.parseToOWLGraph(ontologyIRI); OWLOntology ont = g.getSourceOntology();
The OWLGraphWrapper class provides a wealth of convenience and simple access methods that make coding with OWL ontologies much, much easier.
You can extract standard bio-ontology metadata (as is normally captured in OBO ontologies and in ontologies using the oboInOWL metadata standards) using simple convenience methods:
String label = g.getLabel(c); String def = g.getDef(c); List<ISynonym> syns = g.getOBOSynonyms(c);
By the way, the effectiveness of this sort of utility across a heterogeneous group of ontologies rests on the standardisation of metadata and ID formats across the suite of bio-ontologies, a hard-won goal achieved by OBO Foundry efforts.
There are also convenience classes for rendering the ontology as an image and for printing it neatly to the console for debugging purposes.
2. Working with multiple ontologies at the same time
A challenge in using OWL for engineering ontologies according to the OBO Foundry recommended practice of ontology modularity has been the need to compose developing ontologies from multiple imported modules of other ontologies and bridges to higher-level and upper-level ontologies. Working with the relevant composite ontologies programmatically has been difficult when using the straight OWL API; OWLTools provides a few utilities that make this easier, such as the Multiple Ontologies Concatenation tool Mooncat:
g.addSupportOntologiesFromImportsClosure(); Mooncat mooncat = new Mooncat(emOntoGraph); mooncat.mergeOntologies();
After this step, you can search across all of the terms in the full set of ontologies as if they were a single OWLOntology and accompanying OWLGraphWrapper object -- but the different ID spaces are preserved.
Another handy utility available for working with multiple ontologies at the same time is computing the transitive closure.
3. Analysis method implementations, such as semantic similarity
The library has implementations for various semantic distance measures and different calculations for semantic similarity. For example (taken from the test suite):
OWLGraphWrapper wrapper = getOntologyWrapper("lcstest3.owl"); CombinedJaccardConjunctiveSetSimilarity sa = new CombinedJaccardConjunctiveSetSimilarity(); OWLObject a = wrapper.getOWLObject("http://example.org#axon_terminals_ca2"); OWLObject b = wrapper.getOWLObject("http://example.org#axon_terminals_ca3"); SimEngine se = new SimEngine(wrapper); sa.calculate(se, a, b); sa.print();
You can also, in one line of code, extract minimal OWL-EL modules for super-fast reasoning:
OWLGraphWrapper gEL = InferenceBuilder.enforceEL(g);
And what about performing a diff between two versions of an ontology:
OWLGraphWrapper baseLine = pw.parseToOWLGraph("regulation_xp-baseline.obo"); OWLGraphWrapper change = pw.parseToOWLGraph("regulation_xp_addon.obo"); ReasonerDiff diff = ReasonerDiff.createReasonerDiff(baseLine, change, InferenceBuilder.REASONER_HERMIT); List<OWLAxiom> newAxioms = diff.getNewAxioms(); List<OWLAxiom> rmAxioms = diff.getRemovedInferredAxioms();
4. And much more!
This short introduction was just a taster to get your appetite going. The library contains much more than the simple features that have been described above, including script and web services support. Best of all, it's free and open source. Get started with OWLTools by checking out the source code from the Google code project, and then look at the examples in the JUnit tests. Thanks to the developers of the project and especially to the Berkeley Bioinformatics Open Source Projects team -- keep up the good work!