Skip to content

Commit

Permalink
Merge pull request #579 from ontodev/562-feature
Browse files Browse the repository at this point in the history
Add tautologies & structural-tautologies axiom selectors
  • Loading branch information
jamesaoverton authored Nov 20, 2019
2 parents ab0d9e8 + cbd55b7 commit 13531f6
Show file tree
Hide file tree
Showing 12 changed files with 640 additions and 576 deletions.
317 changes: 50 additions & 267 deletions docs/examples/mitochondrion-full.owl

Large diffs are not rendered by default.

51 changes: 51 additions & 0 deletions docs/examples/no-tautologies.owl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.semanticweb.org/tauber/ontologies/2019/9/untitled-ontology-995#"
xml:base="http://www.semanticweb.org/tauber/ontologies/2019/9/untitled-ontology-995"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://www.semanticweb.org/tauber/ontologies/2019/9/untitled-ontology-995"/>



<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Classes
//
///////////////////////////////////////////////////////////////////////////////////////
-->




<!-- http://robot.obolibrary.org/example/A -->

<owl:Class rdf:about="http://robot.obolibrary.org/example/A">
<rdfs:label>A</rdfs:label>
</owl:Class>



<!-- http://robot.obolibrary.org/example/B -->

<owl:Class rdf:about="http://robot.obolibrary.org/example/B">
<rdfs:subClassOf rdf:resource="http://robot.obolibrary.org/example/A"/>
<rdfs:label>B</rdfs:label>
</owl:Class>



<!-- http://robot.obolibrary.org/example/C -->

<owl:Class rdf:about="http://robot.obolibrary.org/example/C">
<rdfs:label>C</rdfs:label>
</owl:Class>
</rdf:RDF>



<!-- Generated by the OWL API (version 4.5.6) https://github.com/owlcs/owlapi -->

67 changes: 67 additions & 0 deletions docs/examples/tautologies.owl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.semanticweb.org/tauber/ontologies/2019/9/untitled-ontology-995#"
xml:base="http://www.semanticweb.org/tauber/ontologies/2019/9/untitled-ontology-995"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://www.semanticweb.org/tauber/ontologies/2019/9/untitled-ontology-995"/>



<!--
///////////////////////////////////////////////////////////////////////////////////////
//
// Classes
//
///////////////////////////////////////////////////////////////////////////////////////
-->




<!-- http://robot.obolibrary.org/example/A -->

<owl:Class rdf:about="http://robot.obolibrary.org/example/A">
<rdfs:subClassOf rdf:resource="http://robot.obolibrary.org/example/A"/>
<rdfs:label>A</rdfs:label>
</owl:Class>



<!-- http://robot.obolibrary.org/example/B -->

<owl:Class rdf:about="http://robot.obolibrary.org/example/B">
<rdfs:subClassOf rdf:resource="http://robot.obolibrary.org/example/A"/>
<rdfs:label>B</rdfs:label>
</owl:Class>



<!-- http://robot.obolibrary.org/example/C -->

<owl:Class rdf:about="http://robot.obolibrary.org/example/C">
<rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
<rdfs:label>C</rdfs:label>
</owl:Class>



<!-- http://www.w3.org/2002/07/owl#Nothing -->

<owl:Class rdf:about="http://www.w3.org/2002/07/owl#Nothing">
<rdfs:subClassOf rdf:resource="http://robot.obolibrary.org/example/B"/>
</owl:Class>



<!-- http://www.w3.org/2002/07/owl#Thing -->

<owl:Class rdf:about="http://www.w3.org/2002/07/owl#Thing"/>
</rdf:RDF>



<!-- Generated by the OWL API (version 4.2.8.20170104-2310) https://github.com/owlcs/owlapi -->

4 changes: 2 additions & 2 deletions docs/extract.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ By default, `extract` will include imported ontologies. To exclude imported onto
--input imports-nucleus.owl \
--term GO:0005739 \
--imports exclude \
--output mitochondrion.owl
--output results/mitochondrion.owl

This only includes what is asserted in `imports-nucleus.owl`, which imports `nucleus.owl`. `imports-nucleus.owl` only includes the term 'mitochondrion' (`GO:0005739`) and links it to its parent class, 'intracellular membrane-bounded organelle' (`GO:0043231`). `nucleus.owl` contains the full hierarchy down to 'intracellular membrane-bounded organelle'. The output module, `mitochondrion.owl`, only includes the term 'mitochondrion' and this subClassOf statement.

Expand All @@ -146,7 +146,7 @@ By contrast, including imports returns the full hierarchy down to 'mitochondrion
--input imports-nucleus.owl \
--term GO:0005739 \
--imports include \
--output mitochondrion-full.owl
--output results/mitochondrion-full.owl

## Extracting Ontology Annotations

Expand Down
4 changes: 2 additions & 2 deletions docs/filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ Copy a subset of classes based on an annotation property (maintains hierarchy):
--signature true \
--output results/uberon_slim.owl

Copy a class, all axioms that a class appears in, annotations on all the classes (only `UBERON:0000062` here) in the filter set, and the ontology annotations:
Copy a class, all axioms that a class appears in and annotations on all the classes (only `UBERON:0000062` here) in the filter set:

robot filter --input uberon_module.owl \
--term UBERON:0000062 \
--select "ontology annotations" \
--select annotations \
--trim false \
--signature true \
--output results/uberon_annotated.owl
Expand Down
29 changes: 20 additions & 9 deletions docs/remove.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,27 @@ For CURIEs, the pattern must always come after the prefix and colon.

## Axioms

The `--axioms` option allows you to specify the type of OWLAxiom to remove. More than one type can be provided and the order is not significant. For each axiom in the ontology (not including its imports closure), if the axiom implements one of the specified axiom types AND *any* of the selected terms are in the axiom's signature, then the axiom is removed from the ontology.
The `--axioms` option allows you to specify the type of OWLAxiom to remove. More than one type can be provided and these will be processed **in order**. For each axiom in the ontology (not including its imports closure), if the axiom implements one of the specified axiom types AND *any* of the selected terms are in the axiom's signature, then the axiom is removed from the ontology.

Basic axiom selectors select the axiom(s) based on the OWLAPI AxiomType. We have included some special shortcuts to group related axiom types together.
- `all` (default)
- `logical`
- `annotation`
- `subclass`
- `subproperty`
- `equivalent` (classes and properties)
- `disjoint` (classes and properties)
- `type` (class assertions)
- `tbox` (classes and class axioms)
- `abox` (instances and instance-level axioms)
- `rbox` (object properties, aka relations)
- `equivalent`: classes and properties
- `disjoint`: classes and properties
- `type`: class assertions
- `tbox`: classes and class axioms
- `abox`: instances and instance-level axioms
- `rbox`: object properties, i.e., relations
- [OWLAPI AxiomType](http://owlcs.github.io/owlapi/apidocs_4/org/semanticweb/owlapi/model/AxiomType.html) name (e.g., `ObjectPropertyRange`)
- `internal` (all entities that are in one of the `--base-iri` namespaces)
- `external` (all entities that are not in one of the `--base-iri` namespaces)

There are also some special axiom selectors that use additional processing to find certain axioms:
- `internal`: all entities that are in one of the `--base-iri` namespaces
- `external`: all entities that are not in one of the `--base-iri` namespaces
- `tautologies`: all axioms that are *always* true; these would be entailed in an empty ontology. WARNING: this may remove more axioms than desired.
- `structural-tautologies`: all axioms that match a set of tautological patterns (e.g., `X SubClassOf owl:Thing`, `owl:Nothing SubClassOf X`, `X SubClassOf X`)

The `--base-iri <namespace>` is a special option for use with `internal` and `external` axioms. It allows you to specify one or more "base namespaces" (e.g., `--base-iri http://purl.obolibrary.org/obo/OBI_`). You can also use any defined prefix (e.g., `--base-iri OBI`) An axiom is considered internal if the subject is in one of the base namespaces.

Expand Down Expand Up @@ -181,6 +186,12 @@ robot remove --input obi.owl \
--select "owl:deprecated='true'^^xsd:boolean"
```

Remove structural tautologies (e.g., `owl:Nothing`):

robot remove --input tautologies.owl \
--axioms structural-tautologies \
--output results/no-tautologies.owl

Create a "base" subset by removing external axioms (alternatively, use `filter --axioms internal`):

robot remove --input template.owl \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.util.jar.JarFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
Expand Down Expand Up @@ -38,9 +37,6 @@ public class CommandLineHelper {
/** Namespace for general input error messages. */
private static final String NS = "errors#";

/** Error message when --axioms is not a valid AxiomType. Expects: input string. */
private static final String axiomTypeError = NS + "AXIOM TYPE ERROR %s is not a valid axiom type";

/** Error message when a boolean value is not "true" or "false". Expects option name. */
private static final String booleanValueError =
NS + "BOOLEAN VALUE ERROR arg for %s must be true or false";
Expand Down Expand Up @@ -224,6 +220,33 @@ public static boolean hasFlagOrCommand(CommandLine line, String name) {
return command != null && command.equals(name);
}

/**
* Given a command line, get the 'axioms' option(s) and make sure all are properly split and
* return one axiom selector per list entry.
*
* @param line the command line to use
* @return cleaned list of input axiom type strings
*/
public static List<String> cleanAxiomStrings(CommandLine line) {
List<String> axiomTypeStrings = getOptionalValues(line, "axioms");

if (axiomTypeStrings.isEmpty()) {
axiomTypeStrings.add("all");
}

// Split if it's one arg with spaces
List<String> axiomTypeFixedStrings = new ArrayList<>();
for (String axiom : axiomTypeStrings) {
if (axiom.contains(" ")) {
axiomTypeFixedStrings.addAll(Arrays.asList(axiom.split(" ")));
} else {
axiomTypeFixedStrings.add(axiom);
}
}

return axiomTypeFixedStrings;
}

/**
* Given a command line and an IOHelper, return a list of base namespaces from the '--base-iri'
* option.
Expand Down Expand Up @@ -281,78 +304,20 @@ public static boolean getBooleanValue(
/**
* Given a command line, return the value of --axioms as a set of classes that extend OWLAxiom.
*
* @deprecated split into methods {@link #cleanAxiomStrings(CommandLine)} and others in {@link
* org.obolibrary.robot.RelatedObjectsHelper}
* @param line the command line to use
* @return set of OWLAxiom types
*/
@Deprecated
public static Set<Class<? extends OWLAxiom>> getAxiomValues(CommandLine line) {
Set<Class<? extends OWLAxiom>> axiomTypes = new HashSet<>();
List<String> axiomTypeStrings = getOptionValues(line, "axioms");
if (axiomTypeStrings.isEmpty()) {
axiomTypeStrings.add("all");
}
// Split if it's one arg with spaces
List<String> axiomTypeFixedStrings = new ArrayList<>();
for (String axiom : axiomTypeStrings) {
if (axiom.contains(" ")) {
axiomTypeFixedStrings.addAll(Arrays.asList(axiom.split(" ")));
} else {
axiomTypeFixedStrings.add(axiom);
}
}
List<String> axiomTypeStrings = cleanAxiomStrings(line);
// Then get the actual types
for (String axiom : axiomTypeFixedStrings) {
if (axiom.equalsIgnoreCase("internal") || axiom.equalsIgnoreCase("external")) {
// Ignore internal/external axiom options
continue;
}
if (axiom.equalsIgnoreCase("all")) {
axiomTypes.add(OWLAxiom.class);
} else if (axiom.equalsIgnoreCase("logical")) {
axiomTypes.add(OWLLogicalAxiom.class);
} else if (axiom.equalsIgnoreCase("annotation")) {
axiomTypes.add(OWLAnnotationAxiom.class);
} else if (axiom.equalsIgnoreCase("subclass")) {
axiomTypes.add(OWLSubClassOfAxiom.class);
} else if (axiom.equalsIgnoreCase("subproperty")) {
axiomTypes.add(OWLSubObjectPropertyOfAxiom.class);
axiomTypes.add(OWLSubDataPropertyOfAxiom.class);
axiomTypes.add(OWLSubAnnotationPropertyOfAxiom.class);
} else if (axiom.equalsIgnoreCase("equivalent")) {
axiomTypes.add(OWLEquivalentClassesAxiom.class);
axiomTypes.add(OWLEquivalentObjectPropertiesAxiom.class);
axiomTypes.add(OWLEquivalentDataPropertiesAxiom.class);
} else if (axiom.equalsIgnoreCase("disjoint")) {
axiomTypes.add(OWLDisjointClassesAxiom.class);
axiomTypes.add(OWLDisjointObjectPropertiesAxiom.class);
axiomTypes.add(OWLDisjointDataPropertiesAxiom.class);
axiomTypes.add(OWLDisjointUnionAxiom.class);
} else if (axiom.equalsIgnoreCase("type")) {
axiomTypes.add(OWLClassAssertionAxiom.class);
} else if (axiom.equalsIgnoreCase("abox")) {
axiomTypes.addAll(
AxiomType.ABoxAxiomTypes.stream()
.map(AxiomType::getActualClass)
.collect(Collectors.toSet()));
} else if (axiom.equalsIgnoreCase("tbox")) {
axiomTypes.addAll(
AxiomType.TBoxAxiomTypes.stream()
.map(AxiomType::getActualClass)
.collect(Collectors.toSet()));
} else if (axiom.equalsIgnoreCase("rbox")) {
axiomTypes.addAll(
AxiomType.RBoxAxiomTypes.stream()
.map(AxiomType::getActualClass)
.collect(Collectors.toSet()));
} else if (axiom.equalsIgnoreCase("declaration")) {
axiomTypes.add(OWLDeclarationAxiom.class);
} else {
AxiomType<?> at = AxiomType.getAxiomType(axiom);
if (at != null) {
// Attempt to get the axiom type based on AxiomType names
axiomTypes.add(at.getActualClass());
} else {
throw new IllegalArgumentException(String.format(axiomTypeError, axiom));
}
for (String axiom : axiomTypeStrings) {
Set<Class<? extends OWLAxiom>> addTypes = RelatedObjectsHelper.getAxiomValues(axiom);
if (addTypes != null) {
axiomTypes.addAll(addTypes);
}
}
return axiomTypes;
Expand Down
Loading

0 comments on commit 13531f6

Please sign in to comment.