org.obolibrary.robot.MaterializeOperation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of robot-core Show documentation
Show all versions of robot-core Show documentation
Core library for ROBOT: Library for working with OWL ontologies, especially Open Biological and Biomedical Ontologes (OBO).
The newest version!
package org.obolibrary.robot;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.geneontology.reasoner.ExpressionMaterializingReasoner;
import org.geneontology.reasoner.ExpressionMaterializingReasonerFactory;
import org.obolibrary.robot.exceptions.IncoherentTBoxException;
import org.obolibrary.robot.exceptions.OntologyLogicException;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.parameters.Imports;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Materialize SubClassOf axioms using Expression Materializing Reasoner.
*
* @see issue 7
* @author Chris Mungall
*/
public class MaterializeOperation {
/** Logger. */
private static final Logger logger = LoggerFactory.getLogger(MaterializeOperation.class);
/**
* Return a map from option name to default option value, for all the available reasoner options.
*
* @return a map with default values for all available options
*/
public static Map getDefaultOptions() {
Map options = new HashMap<>();
options.put("create-new-ontology", "false");
return options;
}
/**
* Replace EquivalentClass axioms with weaker SubClassOf axioms.
*
* @param ontology The OWLOntology to relax
* @param reasonerFactory reasoner factory for the reasoner that is to be wrapped
* @param properties object properties whose existentials are to be materialized (null
* materializes all)
* @param options A map of options for the operation
* @throws OWLOntologyCreationException if ontology cannot be created
* @throws OntologyLogicException if ontology contains logical errors
*/
public static void materialize(
OWLOntology ontology,
OWLReasonerFactory reasonerFactory,
Set properties,
Map options)
throws OWLOntologyCreationException, OntologyLogicException {
// TODO: make reasonOverImportsClosure optional rather than always true
materialize(ontology, reasonerFactory, properties, options, true);
}
/**
* Replace EquivalentClass axioms with weaker SubClassOf axioms.
*
* @param ontology The OWLOntology to relax
* @param reasonerFactory reasoner factory for the reasoner that is to be wrapped
* @param properties object properties whose existentials are to be materialized (null
* materializes all)
* @param options A map of options for the operation
* @param reasonOverImportsClosure if true will first perform materialization over all ontologies
* in the import closure
* @throws OWLOntologyCreationException on ontology problem
* @throws OntologyLogicException on logic problem
*/
public static void materialize(
OWLOntology ontology,
OWLReasonerFactory reasonerFactory,
Set properties,
Map options,
boolean reasonOverImportsClosure)
throws OntologyLogicException, OWLOntologyCreationException {
if (reasonOverImportsClosure) {
logger.info("Materializing imported ontologies...");
for (OWLOntology importedOntology : ontology.getImportsClosure()) {
if (!importedOntology.equals(ontology)) {
materialize(importedOntology, reasonerFactory, properties, options, false);
}
}
}
logger.info("Materializing: " + ontology);
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
OWLDataFactory dataFactory = manager.getOWLDataFactory();
int seconds;
long elapsedTime;
long startTime = System.currentTimeMillis();
ExpressionMaterializingReasonerFactory merf =
new ExpressionMaterializingReasonerFactory(reasonerFactory);
ExpressionMaterializingReasoner emr = merf.createReasoner(ontology);
ReasonerHelper.validate(emr);
Set newAxioms = new HashSet<>();
// this is entirely for reporting purposes
Map> newAxiomsByProperty = new HashMap<>();
logger.info("Materializing..." + properties);
if (properties == null || properties.size() == 0) {
emr.materializeExpressions();
} else {
emr.materializeExpressions(properties);
}
logger.info("Materialization complete; iterating over classes");
int i = 0;
Imports importsFlag = Imports.EXCLUDED; // TODO - make this optional
Set signature = ontology.getClassesInSignature(importsFlag);
Set axiomsIncludingImports = ontology.getAxioms(Imports.INCLUDED);
for (OWLClass c : signature) {
logger.debug(" Materializing parents of class " + c);
i++;
if (i % 100 == 1) {
logger.info(" Materializing parents of class " + i + "/" + signature.size());
}
if (c.equals(dataFactory.getOWLNothing())) {
continue;
}
if (ontology.getAxioms(c, Imports.EXCLUDED).size() == 0) {
logger.debug("Excluding classes not in main ontology: " + c);
continue;
}
Set sces = emr.getSuperClassExpressions(c, true);
if (!emr.isSatisfiable(c)) {
logger.error("Ontology is not coherent! Unsatisfiable: " + c);
throw new IncoherentTBoxException(Collections.singleton(c));
}
for (OWLClassExpression sce : sces) {
logger.debug(" PARENT: " + sce);
// do not make assertions involving Thing;
// while valid, these are trivial
if (sce.getSignature().contains(dataFactory.getOWLThing())) {
logger.debug("Ignoring: " + sce);
continue;
}
// avoid materializing parents with child in signature;
// this can happen if a property P is reflexive
// -- every class C is a subclass of P some C
// while valid, this is trivial, so we avoid asserting
if (sce.getSignature().contains(c)) {
logger.debug("Signature contains base class: " + sce);
continue;
}
OWLAxiom ax = dataFactory.getOWLSubClassOfAxiom(c, sce);
// skip axioms that already exist
if (axiomsIncludingImports.contains(ax)) {
logger.debug("Already have: " + ax);
continue;
}
newAxioms.add(ax);
// for reporting
for (OWLObjectProperty p : sce.getObjectPropertiesInSignature()) {
if (!newAxiomsByProperty.containsKey(p)) {
newAxiomsByProperty.put(p, new HashSet<>());
}
newAxiomsByProperty.get(p).add(ax);
}
}
}
logger.info("Adding " + newAxioms.size() + " materialized parents");
for (OWLObjectProperty p : newAxiomsByProperty.keySet()) {
logger.info(
" " + p + " generates: " + newAxiomsByProperty.get(p).size() + " materialized parents");
}
if (OptionsHelper.optionIsTrue(options, "create-new-ontology")) {
ontology = manager.createOntology();
}
manager.addAxioms(ontology, newAxioms);
emr.dispose();
elapsedTime = System.currentTimeMillis() - startTime;
seconds = (int) Math.ceil(elapsedTime / 1000);
logger.info("Asserting materialized superclasses took {} seconds.", seconds);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy