diff --git a/docs/examples/mitochondrion-full.owl b/docs/examples/mitochondrion-full.owl
index 5acf4e0ff..2f940dbfb 100644
--- a/docs/examples/mitochondrion-full.owl
+++ b/docs/examples/mitochondrion-full.owl
@@ -29,9 +29,15 @@
-
+
-
+
+
+
+
+
+
+
@@ -137,7 +143,6 @@
A location, relative to cellular compartments and structures, occupied by a macromolecular machine when it carries out a molecular function. There are two ways in which the gene ontology describes locations of gene products: (1) relative to cellular structures (e.g., cytoplasmic side of plasma membrane) or compartments (e.g., mitochondrion), and (2) the stable macromolecular complexes of which they are parts (e.g., the ribosome).
GO:0008372
- NIF_Subcellular:sao-1337158144
NIF_Subcellular:sao1337158144
cell or subcellular entity
cellular component
@@ -160,7 +165,7 @@
A location, relative to cellular compartments and structures, occupied by a macromolecular machine when it carries out a molecular function. There are two ways in which the gene ontology describes locations of gene products: (1) relative to cellular structures (e.g., cytoplasmic side of plasma membrane) or compartments (e.g., mitochondrion), and (2) the stable macromolecular complexes of which they are parts (e.g., the ribosome).
GOC:pdt
- NIF_Subcellular:sao-1337158144
+ NIF_Subcellular:sao1337158144
@@ -174,7 +179,7 @@
-
+
The living contents of a cell; the matter contained within (but not including) the plasma membrane, usually taken to exclude large vacuoles and masses of secretory or ingested material. In eukaryotes it includes the nucleus and cytoplasm.
Wikipedia:Intracellular
internal to cell
@@ -211,34 +216,16 @@
-
-
-
-
- The basic structural and functional unit of all organisms. Includes the plasma membrane and any external encapsulating structures such as the cell wall and cell envelope.
- cell and encapsulating structures
- NIF_Subcellular:sao1813327414
- Wikipedia:Cell_(biology)
- cellular_component
- GO:0005623
-
-
-
- cell
-
-
-
-
- The basic structural and functional unit of all organisms. Includes the plasma membrane and any external encapsulating structures such as the cell wall and cell envelope.
- GOC:go_curators
-
-
-
-
-
+
+
+
+
+
+
+
All of the contents of a cell excluding the plasma membrane and nucleus, but including other subcellular structures.
MIPS_funcat:70.03
Wikipedia:Cytoplasm
@@ -266,7 +253,12 @@
-
+
+
+
+
+
+
A semiautonomous, self replicating organelle that occurs in varying numbers, shapes, and sizes in the cytoplasm of virtually all eukaryotic cells. It is notably the site of tissue respiration.
MIPS_funcat:70.16
NIF_Subcellular:sao1860313010
@@ -300,7 +292,7 @@
-
+
Organized structure of distinctive morphology and function. Includes the nucleus, mitochondria, plastids, vacuoles, vesicles, ribosomes and the cytoskeleton, and prokaryotic structures such as anammoxosomes and pirellulosomes. Excludes the plasma membrane.
NIF_Subcellular:sao1539965131
Wikipedia:Organelle
@@ -355,7 +347,12 @@
-
+
+
+
+
+
+
Organized structure of distinctive morphology and function, occurring within the cell. Includes the nucleus, mitochondria, plastids, vacuoles, vesicles, ribosomes and the cytoskeleton. Excludes the plasma membrane.
cellular_component
GO:0043229
@@ -392,134 +389,13 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Any constituent part of an organelle, an organized structure of distinctive morphology and function. Includes constituent parts of the nucleus, mitochondria, plastids, vacuoles, vesicles, ribosomes and the cytoskeleton, but excludes the plasma membrane.
- cellular_component
- GO:0044422
-
- Note that this term is in the subset of terms that should not be used for direct gene product annotation. Instead, select a child term or, if no appropriate child term exists, please request a new term. Direct annotations to this term may be amended during annotation QC.
- organelle part
-
-
-
-
- Any constituent part of an organelle, an organized structure of distinctive morphology and function. Includes constituent parts of the nucleus, mitochondria, plastids, vacuoles, vesicles, ribosomes and the cytoskeleton, but excludes the plasma membrane.
- GOC:jl
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Any constituent part of the living contents of a cell; the matter contained within (but not including) the plasma membrane, usually taken to exclude large vacuoles and masses of secretory or ingested material. In eukaryotes it includes the nucleus and cytoplasm.
- cellular_component
- GO:0044424
-
- Note that this term is in the subset of terms that should not be used for direct gene product annotation. Instead, select a child term or, if no appropriate child term exists, please request a new term. Direct annotations to this term may be amended during annotation QC.
- intracellular part
-
-
-
-
- Any constituent part of the living contents of a cell; the matter contained within (but not including) the plasma membrane, usually taken to exclude large vacuoles and masses of secretory or ingested material. In eukaryotes it includes the nucleus and cytoplasm.
- GOC:jl
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Any constituent part of a mitochondrion, a semiautonomous, self replicating organelle that occurs in varying numbers, shapes, and sizes in the cytoplasm of virtually all eukaryotic cells. It is notably the site of tissue respiration.
- NIF_Subcellular:sao666410040
- mitochondrial subcomponent
- mitochondrion component
- cellular_component
- GO:0044429
-
- Note that this term is in the subset of terms that should not be used for direct gene product annotation. Instead, select a child term or, if no appropriate child term exists, please request a new term. Direct annotations to this term may be amended during annotation QC.
- mitochondrial part
-
-
-
-
- Any constituent part of a mitochondrion, a semiautonomous, self replicating organelle that occurs in varying numbers, shapes, and sizes in the cytoplasm of virtually all eukaryotic cells. It is notably the site of tissue respiration.
- GOC:jl
-
-
-
-
- mitochondrial subcomponent
- NIF_Subcellular:sao666410040
-
-
-
-
-
+
-
+
-
+
@@ -527,136 +403,43 @@
-
+
- Any constituent part of the cytoplasm, all of the contents of a cell excluding the plasma membrane and nucleus, but including other subcellular structures.
- cytoplasm component
- cellular_component
- GO:0044444
-
- Note that this term is in the subset of terms that should not be used for direct gene product annotation. Instead, select a child term or, if no appropriate child term exists, please request a new term. Direct annotations to this term may be amended during annotation QC.
- cytoplasmic part
-
-
-
-
- Any constituent part of the cytoplasm, all of the contents of a cell excluding the plasma membrane and nucleus, but including other subcellular structures.
- GOC:jl
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- A constituent part of an intracellular organelle, an organized structure of distinctive morphology and function, occurring within the cell. Includes constituent parts of the nucleus, mitochondria, plastids, vacuoles, vesicles, ribosomes and the cytoskeleton but excludes the plasma membrane.
+ Any (proper) part of the cytoplasm of a single cell of sufficient size to still be considered cytoplasm"
cellular_component
- GO:0044446
-
- Note that this term is in the subset of terms that should not be used for direct gene product annotation. Instead, select a child term or, if no appropriate child term exists, please request a new term. Direct annotations to this term may be amended during annotation QC.
- intracellular organelle part
+ GO:0099568
+ cytoplasmic region
-
+
- A constituent part of an intracellular organelle, an organized structure of distinctive morphology and function, occurring within the cell. Includes constituent parts of the nucleus, mitochondria, plastids, vacuoles, vesicles, ribosomes and the cytoskeleton but excludes the plasma membrane.
- GOC:jl
+ Any (proper) part of the cytoplasm of a single cell of sufficient size to still be considered cytoplasm"
+ GOC:dos
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
- Any constituent part of a cell, the basic structural and functional unit of all organisms.
- NIF_Subcellular:sao628508602
- cellular subcomponent
- cellular_component
- protoplast
- GO:0044464
-
-
- Note that this term is in the subset of terms that should not be used for direct gene product annotation. Instead, select a child term or, if no appropriate child term exists, please request a new term. Direct annotations to this term may be amended during annotation QC.
- cell part
-
-
-
-
- Any constituent part of a cell, the basic structural and functional unit of all organisms.
- GOC:jl
-
-
-
-
- cellular subcomponent
- NIF_Subcellular:sao628508602
-
-
-
-
- protoplast
- GOC:mah
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Any (proper) part of the cytoplasm of a single cell of sufficient size to still be considered cytoplasm"
+ A part of a cellular organism that is either an immaterial entity or a material entity with granularity above the level of a protein complex but below that of an anatomical system. Or, a substance produced by a cellular organism with granularity above the level of a protein complex.
+ kmv
+ 2019-08-12T18:01:37Z
cellular_component
- GO:0099568
- cytoplasmic region
+ GO:0110165
+ cellular anatomical entity
-
+
- Any (proper) part of the cytoplasm of a single cell of sufficient size to still be considered cytoplasm"
- GOC:dos
+ A part of a cellular organism that is either an immaterial entity or a material entity with granularity above the level of a protein complex but below that of an anatomical system. Or, a substance produced by a cellular organism with granularity above the level of a protein complex.
+ GOC:kmv
diff --git a/docs/examples/no-tautologies.owl b/docs/examples/no-tautologies.owl
new file mode 100644
index 000000000..81bd9262e
--- /dev/null
+++ b/docs/examples/no-tautologies.owl
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+
+
+
+
+
+
+
+
+ B
+
+
+
+
+
+
+
+ C
+
+
+
+
+
+
+
diff --git a/docs/examples/tautologies.owl b/docs/examples/tautologies.owl
new file mode 100644
index 000000000..ddd3ff57f
--- /dev/null
+++ b/docs/examples/tautologies.owl
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+
+
+
+
+
+
+
+
+ B
+
+
+
+
+
+
+
+
+ C
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/extract.md b/docs/extract.md
index 9bc2e150d..1db05624b 100644
--- a/docs/extract.md
+++ b/docs/extract.md
@@ -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.
@@ -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
diff --git a/docs/filter.md b/docs/filter.md
index 96dffeea9..81cdcda5a 100644
--- a/docs/filter.md
+++ b/docs/filter.md
@@ -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
diff --git a/docs/remove.md b/docs/remove.md
index e50a97f0d..e445ede3f 100644
--- a/docs/remove.md
+++ b/docs/remove.md
@@ -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 ` 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.
@@ -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 \
diff --git a/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java b/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java
index a3dfb388d..df0ba96c0 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/CommandLineHelper.java
@@ -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;
@@ -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";
@@ -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 cleanAxiomStrings(CommandLine line) {
+ List axiomTypeStrings = getOptionalValues(line, "axioms");
+
+ if (axiomTypeStrings.isEmpty()) {
+ axiomTypeStrings.add("all");
+ }
+
+ // Split if it's one arg with spaces
+ List 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.
@@ -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> getAxiomValues(CommandLine line) {
Set> axiomTypes = new HashSet<>();
- List axiomTypeStrings = getOptionValues(line, "axioms");
- if (axiomTypeStrings.isEmpty()) {
- axiomTypeStrings.add("all");
- }
- // Split if it's one arg with spaces
- List axiomTypeFixedStrings = new ArrayList<>();
- for (String axiom : axiomTypeStrings) {
- if (axiom.contains(" ")) {
- axiomTypeFixedStrings.addAll(Arrays.asList(axiom.split(" ")));
- } else {
- axiomTypeFixedStrings.add(axiom);
- }
- }
+ List 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> addTypes = RelatedObjectsHelper.getAxiomValues(axiom);
+ if (addTypes != null) {
+ axiomTypes.addAll(addTypes);
}
}
return axiomTypes;
diff --git a/robot-command/src/main/java/org/obolibrary/robot/FilterCommand.java b/robot-command/src/main/java/org/obolibrary/robot/FilterCommand.java
index 5cd1c01ce..2ebbfa477 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/FilterCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/FilterCommand.java
@@ -170,84 +170,37 @@ public CommandState execute(CommandState state, String[] args) throws Exception
}
// Add the additional axioms to the output ontology
- manager.addAxioms(
- outputOntology,
- getAxioms(line, ioHelper, inputOntology, relatedObjects, includeAnnotations));
-
- // Save the changed ontology and return the state
- CommandLineHelper.maybeSaveOutput(line, outputOntology);
- state.setOntology(outputOntology);
- return state;
- }
-
- /**
- * Given a command line, an IOHelper, an input ontology, a set of objects, and a boolean
- * indicating if annotations on objects should be included, return all axioms for the filtered
- * output.
- *
- * @param line command line to use
- * @param inputOntology input OWLOntology
- * @param relatedObjects set of objects to filter for
- * @param includeAnnotations if true, include all annotations on relatedObjects
- * @return set of OWLAxioms for output ontology
- */
- private static Set getAxioms(
- CommandLine line,
- IOHelper ioHelper,
- OWLOntology inputOntology,
- Set relatedObjects,
- boolean includeAnnotations) {
- // Get a set of axiom types
- boolean internal = false;
- boolean external = false;
- if (line.hasOption("axioms")) {
- for (String ats : CommandLineHelper.getOptionalValue(line, "axioms").split(" ")) {
- if (ats.equalsIgnoreCase("internal")) {
- internal = true;
- } else if (ats.equalsIgnoreCase("external")) {
- external = true;
- }
- }
- }
- Set> axiomTypes = CommandLineHelper.getAxiomValues(line);
-
- // Use these two options to determine which axioms to remove
+ List axiomSelectors = CommandLineHelper.cleanAxiomStrings(line);
+ List baseNamespaces = CommandLineHelper.getBaseNamespaces(line, ioHelper);
boolean trim = CommandLineHelper.getBooleanValue(line, "trim", true);
boolean signature = CommandLineHelper.getBooleanValue(line, "signature", false);
-
- // Get the axioms
- // Use !trim for the 'partial' option in getAxioms
- Set axiomsToAdd =
- RelatedObjectsHelper.getAxioms(inputOntology, relatedObjects, axiomTypes, !trim, signature);
-
- // Then select internal or external, if present
- List baseNamespaces = CommandLineHelper.getBaseNamespaces(line, ioHelper);
- if ((internal || external) && baseNamespaces.isEmpty()) {
- logger.error(
- "No '--base-iri' namespace is specified - internal/external axiom selectors will be ignored.");
- } else {
- if (internal && external) {
- logger.error(
- "Both 'internal' and 'external' axioms are selected - these axiom selectors will be ignored.");
- } else if (internal) {
- axiomsToAdd = RelatedObjectsHelper.getInternalAxioms(baseNamespaces, axiomsToAdd);
- } else if (external) {
- axiomsToAdd = RelatedObjectsHelper.getExternalAxioms(baseNamespaces, axiomsToAdd);
- }
- }
+ manager.addAxioms(
+ outputOntology,
+ RelatedObjectsHelper.filterAxioms(
+ inputOntology.getAxioms(),
+ relatedObjects,
+ axiomSelectors,
+ baseNamespaces,
+ !trim,
+ signature));
// Handle gaps
boolean preserveStructure = CommandLineHelper.getBooleanValue(line, "preserve-structure", true);
if (preserveStructure) {
- axiomsToAdd.addAll(RelatedObjectsHelper.spanGaps(inputOntology, relatedObjects));
+ manager.addAxioms(
+ outputOntology, RelatedObjectsHelper.spanGaps(inputOntology, relatedObjects));
}
- // Handle annotations for any referenced object
+ // Maybe add annotations on the selected objects
if (includeAnnotations) {
- axiomsToAdd.addAll(RelatedObjectsHelper.getAnnotationAxioms(inputOntology, relatedObjects));
+ manager.addAxioms(
+ outputOntology, RelatedObjectsHelper.getAnnotationAxioms(inputOntology, relatedObjects));
}
- return axiomsToAdd;
+ // Save the changed ontology and return the state
+ CommandLineHelper.maybeSaveOutput(line, outputOntology);
+ state.setOntology(outputOntology);
+ return state;
}
/**
diff --git a/robot-command/src/main/java/org/obolibrary/robot/RemoveCommand.java b/robot-command/src/main/java/org/obolibrary/robot/RemoveCommand.java
index c35bbdbe8..45a2ecc3e 100644
--- a/robot-command/src/main/java/org/obolibrary/robot/RemoveCommand.java
+++ b/robot-command/src/main/java/org/obolibrary/robot/RemoveCommand.java
@@ -163,7 +163,14 @@ public CommandState execute(CommandState state, String[] args) throws Exception
OWLManager.createOWLOntologyManager().copyOntology(ontology, OntologyCopy.DEEP);
// Remove specific axioms
- manager.removeAxioms(ontology, getAxioms(line, ioHelper, ontology, relatedObjects));
+ List axiomSelectors = CommandLineHelper.cleanAxiomStrings(line);
+ List baseNamespaces = CommandLineHelper.getBaseNamespaces(line, ioHelper);
+ boolean trim = CommandLineHelper.getBooleanValue(line, "trim", true);
+ boolean signature = CommandLineHelper.getBooleanValue(line, "signature", false);
+ manager.removeAxioms(
+ ontology,
+ RelatedObjectsHelper.filterAxioms(
+ ontology.getAxioms(), relatedObjects, axiomSelectors, baseNamespaces, trim, signature));
// Handle gaps
boolean preserveStructure = CommandLineHelper.getBooleanValue(line, "preserve-structure", true);
@@ -209,23 +216,23 @@ protected static Set getObjects(
}
boolean hadSelection = CommandLineHelper.hasFlagOrCommand(line, "select");
- boolean internal = false;
- boolean external = false;
- if (line.hasOption("axioms")) {
- for (String ats : CommandLineHelper.getOptionalValue(line, "axioms").split(" ")) {
- if (ats.equalsIgnoreCase("internal")) {
- internal = true;
- } else if (ats.equalsIgnoreCase("external")) {
- external = true;
- }
+ boolean axiomSelector = false;
+ List axiomSelectors = CommandLineHelper.cleanAxiomStrings(line);
+ for (String ats : axiomSelectors) {
+ if (ats.equalsIgnoreCase("internal")) {
+ axiomSelector = true;
+ } else if (ats.equalsIgnoreCase("external")) {
+ axiomSelector = true;
+ } else if (ats.contains("tautologies")) {
+ axiomSelector = true;
}
}
- if (hadSelection && selectGroups.isEmpty() && objects.isEmpty() && !internal && !external) {
+ if (hadSelection && selectGroups.isEmpty() && objects.isEmpty() && !axiomSelector) {
// If removing imports or ontology annotations
// and there are no other selects, save and return
return objects;
- } else if (objects.isEmpty() && hasInputIRIs && !internal && !external) {
+ } else if (objects.isEmpty() && hasInputIRIs && !axiomSelector) {
// if objects is empty AND there WERE input IRIs
// there is nothing to remove because the IRIs do not exist in the ontology
return objects;
@@ -268,52 +275,4 @@ protected static Set getObjects(
return relatedObjects;
}
-
- /**
- * Given a command line, an IOHelper, an ontology, and a set of objects, return the related axioms
- * for those objects to remove from the ontology.
- *
- * @param line command line to use
- * @param ioHelper IOHelper to resolve prefixes for base namespaces
- * @param ontology ontology to select axioms from
- * @param relatedObjects objects to select axioms for
- * @return set of axioms to remove
- */
- private static Set getAxioms(
- CommandLine line, IOHelper ioHelper, OWLOntology ontology, Set relatedObjects) {
- // Get a set of axiom types
- boolean internal = false;
- boolean external = false;
- if (line.hasOption("axioms")) {
- for (String ats : CommandLineHelper.getOptionalValue(line, "axioms").split(" ")) {
- if (ats.equalsIgnoreCase("internal")) {
- internal = true;
- } else if (ats.equalsIgnoreCase("external")) {
- external = true;
- }
- }
- }
- Set> axiomTypes = CommandLineHelper.getAxiomValues(line);
-
- // Use these two options to determine which axioms to remove
- boolean trim = CommandLineHelper.getBooleanValue(line, "trim", true);
- boolean signature = CommandLineHelper.getBooleanValue(line, "signature", false);
-
- // Get the axioms and remove them
- Set axiomsToRemove =
- RelatedObjectsHelper.getAxioms(ontology, relatedObjects, axiomTypes, trim, signature);
-
- // Then select internal or external, if present
- List baseNamespaces = CommandLineHelper.getBaseNamespaces(line, ioHelper);
- if (internal && external) {
- logger.warn(
- "Both 'internal' and 'external' axioms are selected - these axiom selectors will be ignored.");
- } else if (internal) {
- axiomsToRemove = RelatedObjectsHelper.getInternalAxioms(baseNamespaces, axiomsToRemove);
- } else if (external) {
- axiomsToRemove = RelatedObjectsHelper.getExternalAxioms(baseNamespaces, axiomsToRemove);
- }
-
- return axiomsToRemove;
- }
}
diff --git a/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java b/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java
index 9bddb9429..caf4282a4 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/ReasonOperation.java
@@ -112,6 +112,81 @@ public static void reason(
assertInferred(ontology, reasoner, gens, options);
}
+ /**
+ * Create a tautology checker.
+ *
+ * @param structural if true, return null - we do not need a checker for the structural patterns
+ * @return new OWLReasoner for empty ontology or null
+ * @throws OWLOntologyCreationException on issue creating empty ontology
+ */
+ public static OWLReasoner getTautologyChecker(boolean structural)
+ throws OWLOntologyCreationException {
+ if (!structural) {
+ OWLOntology empty = OWLManager.createOWLOntologyManager().createOntology();
+ return new ReasonerFactory().createReasoner(empty);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Given an OWLAxiom, a tautology checker reasoner, and a boolean, determine if the axiom is a
+ * tautology.
+ *
+ * @param axiom OWLAxiom to check
+ * @param tautologyChecker OWLReasoner for empty ontology
+ * @param structural if true, only check for hard-coded structural patterns (checker can be null)
+ * @return true if axiom is tautological
+ */
+ public static boolean isTautological(
+ OWLAxiom axiom, OWLReasoner tautologyChecker, boolean structural) {
+ if (structural) {
+ if (axiom instanceof OWLSubClassOfAxiom) {
+ OWLSubClassOfAxiom subClassOfAxiom = (OWLSubClassOfAxiom) axiom;
+ if (subClassOfAxiom.getSuperClass().isOWLThing()) {
+ // X subClassOf owl:Thing
+ return true;
+ } else if (subClassOfAxiom.getSubClass().isOWLNothing()) {
+ // owl:Nothing subClassOf X
+ return true;
+ } else {
+ // X subClassOf X
+ return subClassOfAxiom.getSubClass().equals(subClassOfAxiom.getSuperClass());
+ }
+ } else if (axiom instanceof OWLEquivalentClassesAxiom) {
+ // X equivalentTo X
+ OWLEquivalentClassesAxiom equivAxiom = (OWLEquivalentClassesAxiom) axiom;
+ return equivAxiom.getClassExpressions().size() < 2;
+ } else if (axiom instanceof OWLClassAssertionAxiom) {
+ // X a owl:Thing
+ OWLClassAssertionAxiom classAssertion = (OWLClassAssertionAxiom) axiom;
+ return classAssertion.getClassExpression().isOWLThing();
+ } else if (axiom instanceof OWLObjectPropertyAssertionAxiom) {
+ // X owl:topDataProperty ...
+ OWLObjectPropertyAssertionAxiom assertion = (OWLObjectPropertyAssertionAxiom) axiom;
+ return assertion.getProperty().isOWLTopObjectProperty();
+ } else if (axiom instanceof OWLDataPropertyAssertionAxiom) {
+ // X owl:topObjectProperty ...
+ OWLDataPropertyAssertionAxiom assertion = (OWLDataPropertyAssertionAxiom) axiom;
+ return assertion.getProperty().isOWLTopDataProperty();
+ } else if (axiom instanceof OWLDeclarationAxiom) {
+ // owl:Thing a owl:Class, owl:Nothing a owl:Class, etc.
+ OWLDeclarationAxiom declaration = (OWLDeclarationAxiom) axiom;
+ return declaration.getEntity().isBuiltIn();
+ }
+ } else if (tautologyChecker != null) {
+ if (axiom instanceof OWLDeclarationAxiom) {
+ // ignore declaration UNLESS it is built in
+ OWLDeclarationAxiom declaration = (OWLDeclarationAxiom) axiom;
+ return declaration.getEntity().isBuiltIn();
+ } else if (axiom instanceof OWLLogicalAxiom) {
+ // otherwise check if axiom is entailed by empty ontology
+ return tautologyChecker.isEntailed(axiom);
+ }
+ }
+ return false;
+ }
+
/**
* Remove subClassAxioms where there is a more direct axiom, and the subClassAxiom does not have
* any annotations.
@@ -383,13 +458,9 @@ private static void addInferredAxioms(
// If we will need a tautology checker, create it only once
String tautologiesOption = OptionsHelper.getOption(options, "exclude-tautologies", "false");
- OWLReasoner tautologyChecker;
- if (tautologiesOption.equalsIgnoreCase("all")) {
- OWLOntology empty = OWLManager.createOWLOntologyManager().createOntology();
- tautologyChecker = new ReasonerFactory().createReasoner(empty);
- } else {
- tautologyChecker = null;
- }
+ boolean excludeTautologies = !tautologiesOption.equalsIgnoreCase("false");
+ boolean structural = tautologiesOption.equalsIgnoreCase("structural");
+ OWLReasoner tautologyChecker = getTautologyChecker(structural);
// Look at each inferred axiom
// Check the options, and maybe add the inferred axiom to the ontology
@@ -437,41 +508,9 @@ private static void addInferredAxioms(
}
}
- if (tautologiesOption.equalsIgnoreCase("structural")) {
- if (a instanceof OWLSubClassOfAxiom) {
- OWLSubClassOfAxiom subClassOfAxiom = (OWLSubClassOfAxiom) a;
- if (subClassOfAxiom.getSuperClass().isOWLThing()) {
- continue;
- } else if (subClassOfAxiom.getSubClass().isOWLNothing()) {
- continue;
- } else if (subClassOfAxiom.getSubClass().equals(subClassOfAxiom.getSuperClass())) {
- continue;
- }
- } else if (a instanceof OWLEquivalentClassesAxiom) {
- OWLEquivalentClassesAxiom equivAxiom = (OWLEquivalentClassesAxiom) a;
- if (equivAxiom.getClassExpressions().size() < 2) {
- continue;
- }
- } else if (a instanceof OWLClassAssertionAxiom) {
- OWLClassAssertionAxiom classAssertion = (OWLClassAssertionAxiom) a;
- if (classAssertion.getClassExpression().isOWLThing()) {
- continue;
- }
- } else if (a instanceof OWLObjectPropertyAssertionAxiom) {
- OWLObjectPropertyAssertionAxiom assertion = (OWLObjectPropertyAssertionAxiom) a;
- if (assertion.getProperty().isOWLTopObjectProperty()) {
- continue;
- }
- } else if (a instanceof OWLDataPropertyAssertionAxiom) {
- OWLDataPropertyAssertionAxiom assertion = (OWLDataPropertyAssertionAxiom) a;
- if (assertion.getProperty().isOWLTopDataProperty()) {
- continue;
- }
- }
- } else if (tautologiesOption.equalsIgnoreCase("all") && (tautologyChecker != null)) {
- if (tautologyChecker.isEntailed(a)) {
- continue;
- }
+ // Maybe exclude tautologies
+ if (excludeTautologies && isTautological(a, tautologyChecker, structural)) {
+ continue;
}
// If the axiom has not been skipped, add it to the ontology
@@ -496,7 +535,7 @@ private static void checkReferenceViolations(OWLOntology ontology, Map referenceViolations =
InvalidReferenceChecker.getInvalidReferenceViolations(ontology, false);
- Set filteredViolations = new HashSet();
+ Set filteredViolations = new HashSet<>();
if (referenceViolations.size() > 0) {
for (InvalidReferenceViolation v : referenceViolations) {
diff --git a/robot-core/src/main/java/org/obolibrary/robot/RelatedObjectsHelper.java b/robot-core/src/main/java/org/obolibrary/robot/RelatedObjectsHelper.java
index 06b443d83..4b98feb92 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/RelatedObjectsHelper.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/RelatedObjectsHelper.java
@@ -4,9 +4,11 @@
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.*;
import org.semanticweb.owlapi.model.parameters.Imports;
+import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.search.EntitySearcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,6 +30,9 @@ public class RelatedObjectsHelper {
/** Namespace for 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 datatype is given for an annotation, but the annotation value does not
* match the datatype.
@@ -81,52 +86,107 @@ public static Set getAnnotationAxioms(OWLOntology ontology, Set getAxioms(
- OWLOntology ontology,
+ /**
+ * Filter a set of OWLAxioms based on the provided arguments.
+ *
+ * @param axioms Set of OWLAxioms to filter
+ * @param objects Set of OWLObjects to get axioms for
+ * @param axiomSelectors List of string selectors for types of axioms
+ * @param baseNamespaces List of string base namespaces used for internal/external selections
+ * @param partial if true, get any axiom containing at least one OWLObject from objects
+ * @param namedOnly if true, ignore anonymous OWLObjects in axioms
+ * @return set of filtered OWLAxioms
+ * @throws OWLOntologyCreationException on issue creating empty ontology for tautology checker
+ */
+ public static Set filterAxioms(
+ Set axioms,
Set objects,
- Set> axiomTypes,
+ List axiomSelectors,
+ List baseNamespaces,
boolean partial,
- boolean signature) {
- if (partial) {
- return RelatedObjectsHelper.getPartialAxioms(ontology, objects, axiomTypes, signature);
- } else {
- return RelatedObjectsHelper.getCompleteAxioms(ontology, objects, axiomTypes, signature);
+ boolean namedOnly)
+ throws OWLOntologyCreationException {
+
+ // Go through the axiom selectors in order and process selections
+ boolean internal = false;
+ boolean external = false;
+ for (String axiomSelector : axiomSelectors) {
+ if (axiomSelector.equalsIgnoreCase("internal")) {
+ if (external) {
+ logger.error(
+ "ignoring 'internal' axiom selector - 'internal' and 'external' together will remove all axioms");
+ }
+ axioms = RelatedObjectsHelper.filterInternalAxioms(axioms, baseNamespaces);
+ internal = true;
+ } else if (axiomSelector.equalsIgnoreCase("external")) {
+ if (internal) {
+ logger.error(
+ "ignoring 'external' axiom selector - 'internal' and 'external' together will remove all axioms");
+ }
+ axioms = RelatedObjectsHelper.filterExternalAxioms(axioms, baseNamespaces);
+ external = true;
+ } else if (axiomSelector.equalsIgnoreCase("tautologies")) {
+ axioms = RelatedObjectsHelper.filterTautologicalAxioms(axioms, false);
+ } else if (axiomSelector.equalsIgnoreCase("structural-tautologies")) {
+ axioms = RelatedObjectsHelper.filterTautologicalAxioms(axioms, true);
+ } else {
+ // Assume this is a normal OWLAxiom type
+ Set> axiomTypes =
+ RelatedObjectsHelper.getAxiomValues(axiomSelector);
+ axioms = filterAxiomsByAxiomType(axioms, objects, axiomTypes, partial, namedOnly);
+ }
}
+
+ return axioms;
}
/**
- * Given an ontology, a set of objects, and a set of axiom types, return a set of axioms where all
- * the objects in those axioms are in the set of objects.
+ * Given a set of OWLAxioms, a set of OWLObjects, a set of OWLAxiom Classes, a partial boolean,
+ * and a named-only boolean, return a set of OWLAxioms based on OWLAxiom type. The axiom is added
+ * to the set if it is an instance of an OWLAxiom Class in the axiomTypes set. If partial, return
+ * any axioms that use at least one object from the objects set. Otherwise, only return axioms
+ * that use objects in the set. If namedOnly, only consider named OWLObjects in the axioms and
+ * ignore any anonymous objects when selecting the axioms.
*
- * @param ontology OWLOntology to get axioms from
- * @param objects Set of objects to match in axioms
- * @param axiomTypes OWLAxiom types to return
- * @return Set of OWLAxioms containing only the OWLObjects
+ * @param axioms set of OWLAxioms to filter
+ * @param objects set of OWLObjects to get axioms for
+ * @param axiomTypes set of OWLAxiom Classes that determines what type of axioms will be selected
+ * @param partial if true, include all axioms that use at least one OWLObject from objects
+ * @param namedOnly if true, ignore anonymous OWLObjects used in axioms
+ * @return set of filtered axioms
*/
- public static Set getCompleteAxioms(
- OWLOntology ontology, Set objects, Set> axiomTypes) {
- return getCompleteAxioms(ontology, objects, axiomTypes, false);
+ public static Set filterAxiomsByAxiomType(
+ Set axioms,
+ Set objects,
+ Set> axiomTypes,
+ boolean partial,
+ boolean namedOnly) {
+ if (partial) {
+ return RelatedObjectsHelper.filterPartialAxioms(axioms, objects, axiomTypes, namedOnly);
+ } else {
+ return RelatedObjectsHelper.filterCompleteAxioms(axioms, objects, axiomTypes, namedOnly);
+ }
}
/**
- * Given an ontology, a set of objects, and a set of axiom types, return a set of axioms where all
- * the objects in those axioms are in the set of objects.
+ * Given a st of axioms, a set of objects, and a set of axiom types, return a set of axioms where
+ * all the objects in those axioms are in the set of objects.
*
- * @param ontology OWLOntology to get axioms from
+ * @param inputAxioms Set of OWLAxioms to filter
* @param objects Set of objects to match in axioms
* @param axiomTypes OWLAxiom types to return
* @param namedOnly when true, consider only named OWLObjects
* @return Set of OWLAxioms containing only the OWLObjects
*/
- public static Set getCompleteAxioms(
- OWLOntology ontology,
+ public static Set filterCompleteAxioms(
+ Set inputAxioms,
Set objects,
Set> axiomTypes,
boolean namedOnly) {
axiomTypes = setDefaultAxiomType(axiomTypes);
Set axioms = new HashSet<>();
Set iris = getIRIs(objects);
- for (OWLAxiom axiom : ontology.getAxioms()) {
+ for (OWLAxiom axiom : inputAxioms) {
if (OntologyHelper.extendsAxiomTypes(axiom, axiomTypes)) {
// Check both the full annotated axiom and axiom without annotations (if annotated)
Set axiomObjects;
@@ -180,11 +240,12 @@ public static Set getCompleteAxioms(
* Given a list of base namespaces and a set of axioms, return only the axioms that DO NOT have a
* subject in the base namespaces.
*
- * @param baseNamespaces list of base namespaces
* @param axioms set of OWLAxioms
+ * @param baseNamespaces list of base namespaces
* @return external OWLAxioms
*/
- public static Set getExternalAxioms(List baseNamespaces, Set axioms) {
+ public static Set filterExternalAxioms(
+ Set axioms, List baseNamespaces) {
Set externalAxioms = new HashSet<>();
for (OWLAxiom axiom : axioms) {
Set subjects = getAxiomSubjects(axiom);
@@ -199,11 +260,12 @@ public static Set getExternalAxioms(List baseNamespaces, Set getInternalAxioms(List baseNamespaces, Set axioms) {
+ public static Set filterInternalAxioms(
+ Set axioms, List baseNamespaces) {
Set internalAxioms = new HashSet<>();
for (OWLAxiom axiom : axioms) {
Set subjects = getAxiomSubjects(axiom);
@@ -215,38 +277,24 @@ public static Set getInternalAxioms(List baseNamespaces, Set getPartialAxioms(
- OWLOntology ontology, Set objects, Set> axiomTypes) {
- return getPartialAxioms(ontology, objects, axiomTypes, false);
- }
-
- /**
- * Given an ontology, a set of objects, and a set of axiom types, return a set of axioms where at
- * least one object in those axioms is also in the set of objects.
- *
- * @param ontology OWLOntology to get axioms from
- * @param objects Set of objects to match in axioms
+ * @param inputAxioms Set of OWLAxioms to filter
+ * @param objects Set of OWLObjects to match in axioms
* @param axiomTypes OWLAxiom types to return
* @param namedOnly when true, only consider named OWLObjects
* @return Set of OWLAxioms containing at least one of the OWLObjects
*/
- public static Set getPartialAxioms(
- OWLOntology ontology,
+ public static Set filterPartialAxioms(
+ Set inputAxioms,
Set objects,
Set> axiomTypes,
boolean namedOnly) {
axiomTypes = setDefaultAxiomType(axiomTypes);
Set axioms = new HashSet<>();
Set iris = getIRIs(objects);
- for (OWLAxiom axiom : ontology.getAxioms()) {
+ for (OWLAxiom axiom : inputAxioms) {
if (OntologyHelper.extendsAxiomTypes(axiom, axiomTypes)) {
if (axiom instanceof OWLAnnotationAssertionAxiom) {
OWLAnnotationAssertionAxiom a = (OWLAnnotationAssertionAxiom) axiom;
@@ -283,6 +331,190 @@ public static Set getPartialAxioms(
return axioms;
}
+ /**
+ * Given a set of OWLAxioms and a structural boolean, filter for tautological axioms, i.e., those
+ * that would be true in any ontology.
+ *
+ * @param axioms set of OWLAxioms to filter
+ * @param structural if true, only filter for structural tautological axioms based on a hard-coded
+ * set of patterns (e.g., X subClassOf owl:Thing, owl:Nothing subClassOf X, X subClassOf X)
+ * @return tautological OWLAxioms from original set
+ * @throws OWLOntologyCreationException on issue creating empty ontology for tautology checker
+ */
+ public static Set filterTautologicalAxioms(Set axioms, boolean structural)
+ throws OWLOntologyCreationException {
+ // If structural, checker will be null
+ OWLReasoner tautologyChecker = ReasonOperation.getTautologyChecker(structural);
+ Set tautologies = new HashSet<>();
+ for (OWLAxiom a : axioms) {
+ if (ReasonOperation.isTautological(a, tautologyChecker, structural)) {
+ tautologies.add(a);
+ }
+ }
+ return tautologies;
+ }
+
+ /**
+ * @deprecated replaced by {@link #filterAxiomsByAxiomType(Set, Set, Set, boolean, boolean)}
+ * @param ontology OWLOntology to get axioms from
+ * @param objects OWLObjects to get axioms about
+ * @param axiomTypes Set of OWLAxiom Classes that are the types of OWLAxioms to return
+ * @param partial if true, return any OWLAxiom that has at least one OWLObject from objects
+ * @param signature if true, ignore anonymous OWLObjects in axioms
+ * @return axioms from ontology based on options
+ */
+ @Deprecated
+ public static Set getAxioms(
+ OWLOntology ontology,
+ Set objects,
+ Set> axiomTypes,
+ boolean partial,
+ boolean signature) {
+ if (partial) {
+ return RelatedObjectsHelper.getPartialAxioms(ontology, objects, axiomTypes, signature);
+ } else {
+ return RelatedObjectsHelper.getCompleteAxioms(ontology, objects, axiomTypes, signature);
+ }
+ }
+
+ /**
+ * Given a string axiom selector, return the OWLAxiom Class type(s) or null. The selector is
+ * either a special keyword that represents a set of axiom classes or the name of an OWLAxiom
+ * Class.
+ *
+ * @param axiomSelector string option to get the OWLAxiom Class type or types for
+ * @return set of OWLAxiom Class types based on the string option
+ */
+ public static Set> getAxiomValues(String axiomSelector) {
+ Set ignore =
+ new HashSet<>(
+ Arrays.asList("internal", "external", "tautologies", "structural-tautologies"));
+ if (ignore.contains(axiomSelector)) {
+ // Ignore special axiom options
+ return null;
+ }
+
+ Set> axiomTypes = new HashSet<>();
+ if (axiomSelector.equalsIgnoreCase("all")) {
+ axiomTypes.add(OWLAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("logical")) {
+ axiomTypes.add(OWLLogicalAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("annotation")) {
+ axiomTypes.add(OWLAnnotationAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("subclass")) {
+ axiomTypes.add(OWLSubClassOfAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("subproperty")) {
+ axiomTypes.add(OWLSubObjectPropertyOfAxiom.class);
+ axiomTypes.add(OWLSubDataPropertyOfAxiom.class);
+ axiomTypes.add(OWLSubAnnotationPropertyOfAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("equivalent")) {
+ axiomTypes.add(OWLEquivalentClassesAxiom.class);
+ axiomTypes.add(OWLEquivalentObjectPropertiesAxiom.class);
+ axiomTypes.add(OWLEquivalentDataPropertiesAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("disjoint")) {
+ axiomTypes.add(OWLDisjointClassesAxiom.class);
+ axiomTypes.add(OWLDisjointObjectPropertiesAxiom.class);
+ axiomTypes.add(OWLDisjointDataPropertiesAxiom.class);
+ axiomTypes.add(OWLDisjointUnionAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("type")) {
+ axiomTypes.add(OWLClassAssertionAxiom.class);
+ } else if (axiomSelector.equalsIgnoreCase("abox")) {
+ axiomTypes.addAll(
+ AxiomType.ABoxAxiomTypes.stream()
+ .map(AxiomType::getActualClass)
+ .collect(Collectors.toSet()));
+ } else if (axiomSelector.equalsIgnoreCase("tbox")) {
+ axiomTypes.addAll(
+ AxiomType.TBoxAxiomTypes.stream()
+ .map(AxiomType::getActualClass)
+ .collect(Collectors.toSet()));
+ } else if (axiomSelector.equalsIgnoreCase("rbox")) {
+ axiomTypes.addAll(
+ AxiomType.RBoxAxiomTypes.stream()
+ .map(AxiomType::getActualClass)
+ .collect(Collectors.toSet()));
+ } else if (axiomSelector.equalsIgnoreCase("declaration")) {
+ axiomTypes.add(OWLDeclarationAxiom.class);
+ } else {
+ AxiomType> at = AxiomType.getAxiomType(axiomSelector);
+ if (at != null) {
+ // Attempt to get the axiom type based on AxiomType names
+ axiomTypes.add(at.getActualClass());
+ } else {
+ throw new IllegalArgumentException(String.format(axiomTypeError, axiomSelector));
+ }
+ }
+ return axiomTypes;
+ }
+
+ /**
+ * Given an ontology, a set of objects, and a set of axiom types, return a set of axioms where all
+ * the objects in those axioms are in the set of objects. Prefer {@link #filterCompleteAxioms(Set,
+ * Set, Set, boolean)}.
+ *
+ * @param ontology OWLOntology to get axioms from
+ * @param objects Set of objects to match in axioms
+ * @param axiomTypes OWLAxiom types to return
+ * @return Set of OWLAxioms containing only the OWLObjects
+ */
+ public static Set getCompleteAxioms(
+ OWLOntology ontology, Set objects, Set> axiomTypes) {
+ return filterCompleteAxioms(ontology.getAxioms(), objects, axiomTypes, false);
+ }
+
+ /**
+ * Given an ontology, a set of objects, and a set of axiom types, return a set of axioms where all
+ * the objects in those axioms are in the set of objects. Prefer {@link #filterCompleteAxioms(Set,
+ * Set, Set, boolean)}.
+ *
+ * @param ontology OWLOntology to get axioms from
+ * @param objects Set of objects to match in axioms
+ * @param axiomTypes OWLAxiom types to return
+ * @param namedOnly when true, consider only named OWLObjects
+ * @return Set of OWLAxioms containing only the OWLObjects
+ */
+ public static Set getCompleteAxioms(
+ OWLOntology ontology,
+ Set objects,
+ Set> axiomTypes,
+ boolean namedOnly) {
+ return filterCompleteAxioms(ontology.getAxioms(), objects, axiomTypes, namedOnly);
+ }
+
+ /**
+ * Given an ontology, a set of objects, and a set of axiom types, return a set of axioms where at
+ * least one object in those axioms is also in the set of objects. Prefer {@link
+ * #filterPartialAxioms(Set, Set, Set, boolean)}.
+ *
+ * @param ontology OWLOntology to get axioms from
+ * @param objects Set of objects to match in axioms
+ * @param axiomTypes OWLAxiom types to return
+ * @return Set of OWLAxioms containing at least one of the OWLObjects
+ */
+ public static Set getPartialAxioms(
+ OWLOntology ontology, Set objects, Set> axiomTypes) {
+ return filterPartialAxioms(ontology.getAxioms(), objects, axiomTypes, false);
+ }
+
+ /**
+ * Given an ontology, a set of objects, and a set of axiom types, return a set of axioms where at
+ * least one object in those axioms is also in the set of objects. Prefer {@link
+ * #filterPartialAxioms(Set, Set, Set, boolean)}.
+ *
+ * @param ontology OWLOntology to get axioms from
+ * @param objects Set of objects to match in axioms
+ * @param axiomTypes OWLAxiom types to return
+ * @param namedOnly when true, only consider named OWLObjects
+ * @return Set of OWLAxioms containing at least one of the OWLObjects
+ */
+ public static Set getPartialAxioms(
+ OWLOntology ontology,
+ Set objects,
+ Set> axiomTypes,
+ boolean namedOnly) {
+ return filterPartialAxioms(ontology.getAxioms(), objects, axiomTypes, namedOnly);
+ }
+
/**
* Given an ontology, a set of objects, and a list of select groups (as lists), return the objects
* related to the set of OWLObjects based on each set of selectors. Each selector group will build
diff --git a/robot-core/src/test/java/org/obolibrary/robot/RelatedObjectsHelperTest.java b/robot-core/src/test/java/org/obolibrary/robot/RelatedObjectsHelperTest.java
index d860211dd..5cc46afc8 100644
--- a/robot-core/src/test/java/org/obolibrary/robot/RelatedObjectsHelperTest.java
+++ b/robot-core/src/test/java/org/obolibrary/robot/RelatedObjectsHelperTest.java
@@ -32,13 +32,13 @@ public class RelatedObjectsHelperTest extends CoreTest {
"comment 2", df.getOWLDatatype(IRI.create("http://example.com/test-datatype-2"))));
/**
- * Test getting complete axioms.
+ * Test filtering for complete axioms.
*
* @throws IOException on any problem
*/
@Test
@SuppressWarnings("unchecked")
- public void testGetCompleteAxioms() throws IOException {
+ public void testFilterCompleteAxioms() throws IOException {
IOHelper ioHelper = new IOHelper();
String base = "https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#";
Set objects;
@@ -51,25 +51,27 @@ public void testGetCompleteAxioms() throws IOException {
objects.add(df.getOWLClass(IRI.create(base + "test1")));
objects.add(df.getOWLClass(IRI.create(base + "test2")));
axiomTypes = Sets.newHashSet(OWLSubClassOfAxiom.class);
- axioms = RelatedObjectsHelper.getCompleteAxioms(ontology, objects, axiomTypes);
+ axioms =
+ RelatedObjectsHelper.filterCompleteAxioms(ontology.getAxioms(), objects, axiomTypes, false);
assertEquals(1, axioms.size());
objects = new HashSet<>();
objects.add(df.getOWLClass(IRI.create(base + "test1")));
objects.add(df.getOWLAnnotationProperty(ioHelper.createIRI("rdfs:label")));
axiomTypes = Sets.newHashSet(OWLAnnotationAssertionAxiom.class);
- axioms = RelatedObjectsHelper.getCompleteAxioms(ontology, objects, axiomTypes);
+ axioms =
+ RelatedObjectsHelper.filterCompleteAxioms(ontology.getAxioms(), objects, axiomTypes, false);
assertEquals(2, axioms.size());
}
/**
- * Test getting partial axioms.
+ * Test filtering for partial axioms.
*
* @throws IOException on any problem
*/
@Test
@SuppressWarnings("unchecked")
- public void testGetPartialAxioms() throws IOException {
+ public void testFilterPartialAxioms() throws IOException {
IOHelper ioHelper = new IOHelper();
String base = "https://github.com/ontodev/robot/robot-core/src/test/resources/simple.owl#";
Set objects;
@@ -81,13 +83,15 @@ public void testGetPartialAxioms() throws IOException {
objects = new HashSet<>();
objects.add(df.getOWLClass(IRI.create(base + "test1")));
axiomTypes = Sets.newHashSet(OWLSubClassOfAxiom.class);
- axioms = RelatedObjectsHelper.getPartialAxioms(ontology, objects, axiomTypes);
+ axioms =
+ RelatedObjectsHelper.filterPartialAxioms(ontology.getAxioms(), objects, axiomTypes, false);
assertEquals(1, axioms.size());
objects = new HashSet<>();
objects.add(df.getOWLAnnotationProperty(ioHelper.createIRI("rdfs:label")));
axiomTypes = Sets.newHashSet(OWLAnnotationAssertionAxiom.class);
- axioms = RelatedObjectsHelper.getPartialAxioms(ontology, objects, axiomTypes);
+ axioms =
+ RelatedObjectsHelper.filterPartialAxioms(ontology.getAxioms(), objects, axiomTypes, false);
assertEquals(2, axioms.size());
}