From 08872bef730e242c3ba0bddf252a00fd4d5c8192 Mon Sep 17 00:00:00 2001 From: Damien Goutte-Gattat Date: Tue, 25 Mar 2025 22:01:01 +0000 Subject: [PATCH 1/3] Allow selecting punned entities in remove/filter. Add a `--allow-punning` option to the `remove` and `filter` command. When enabled, if a given IRI to select corresponds to several punned entities, all corresponding entities will be selected (contrary to the default behaviour, which is completely ignore all punned entities). --- .../org/obolibrary/robot/FilterCommand.java | 1 + .../org/obolibrary/robot/RemoveCommand.java | 10 +++-- .../org/obolibrary/robot/OntologyHelper.java | 40 ++++++++++++++----- 3 files changed, 37 insertions(+), 14 deletions(-) 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 aca9a5a91..abd5f1979 100644 --- a/robot-command/src/main/java/org/obolibrary/robot/FilterCommand.java +++ b/robot-command/src/main/java/org/obolibrary/robot/FilterCommand.java @@ -49,6 +49,7 @@ public FilterCommand() { "drop-axiom-annotations", true, "drop all axiom annotations involving a particular annotation property"); + o.addOption(null, "allow-punning", true, "if true, allow selecting punned entities"); options = o; } 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 034e6046a..05cfe0f9f 100644 --- a/robot-command/src/main/java/org/obolibrary/robot/RemoveCommand.java +++ b/robot-command/src/main/java/org/obolibrary/robot/RemoveCommand.java @@ -51,6 +51,7 @@ public RemoveCommand() { "drop-axiom-annotations", true, "drop all axiom annotations involving a particular annotation property"); + o.addOption(null, "allow-punning", true, "if true, allow selecting punned entities"); options = o; } @@ -238,10 +239,11 @@ protected static Set getObjects( Set objects = new HashSet<>(); // track if a set of input IRIs were provided boolean hasInputIRIs = false; + boolean punning = CommandLineHelper.getBooleanValue(line, "allow-punning", false); if (line.hasOption("term") || line.hasOption("term-file")) { Set entityIRIs = CommandLineHelper.getTerms(ioHelper, line, "term", "term-file"); if (!entityIRIs.isEmpty()) { - objects.addAll(OntologyHelper.getEntities(ontology, entityIRIs)); + objects.addAll(OntologyHelper.getEntities(ontology, entityIRIs, punning)); hasInputIRIs = true; } } @@ -282,7 +284,7 @@ protected static Set getObjects( Set includeIRIs = CommandLineHelper.getTerms(ioHelper, line, "include-term", "include-terms"); Set includeObjects = - new HashSet<>(OntologyHelper.getEntities(ontology, includeIRIs)); + new HashSet<>(OntologyHelper.getEntities(ontology, includeIRIs, punning)); relatedObjects.addAll(includeObjects); } @@ -291,7 +293,7 @@ protected static Set getObjects( Set excludeIRIs = CommandLineHelper.getTerms(ioHelper, line, "exclude-term", "exclude-terms"); Set excludeObjects = - new HashSet<>(OntologyHelper.getEntities(ontology, excludeIRIs)); + new HashSet<>(OntologyHelper.getEntities(ontology, excludeIRIs, punning)); relatedObjects.removeAll(excludeObjects); } @@ -300,7 +302,7 @@ protected static Set getObjects( Set includeIRIs = CommandLineHelper.getTerms(ioHelper, line, "include-term", "include-terms"); Set includeObjects = - new HashSet<>(OntologyHelper.getEntities(ontology, includeIRIs)); + new HashSet<>(OntologyHelper.getEntities(ontology, includeIRIs, punning)); relatedObjects.addAll(includeObjects); } diff --git a/robot-core/src/main/java/org/obolibrary/robot/OntologyHelper.java b/robot-core/src/main/java/org/obolibrary/robot/OntologyHelper.java index 62b490ed0..4ec405e3d 100644 --- a/robot-core/src/main/java/org/obolibrary/robot/OntologyHelper.java +++ b/robot-core/src/main/java/org/obolibrary/robot/OntologyHelper.java @@ -1217,21 +1217,41 @@ public static OWLEntity getEntity(OWLOntology ontology, IRI iri, boolean allowNu * @return a set of OWLEntities with the given IRIs */ public static Set getEntities(OWLOntology ontology, Set iris) { + return getEntities(ontology, iris, false); + } + + /** + * Given an ontology and a set of term IRIs, return a set of entities for those IRIs. The input + * ontology is not changed. + * + * @param ontology The ontology to search + * @param iris the IRIs of the entities to find + * @param allowPunning if true, will return all entities punned to the same IRI; otherwise, all + * punned entities are ignored + * @return a set of OWLEntities with the given IRIs + */ + public static Set getEntities( + OWLOntology ontology, Set iris, boolean allowPunning) { Set entities = new HashSet<>(); if (iris == null) { return entities; } for (IRI iri : iris) { - OWLEntity entity; - try { - entity = getEntity(ontology, iri, true); - } catch (Exception e) { - // This block shouldn't get hit, but just in case, skip this entity - entity = null; - } - if (entity != null) { - // Do not add null entries - entities.add(entity); + if (allowPunning) { + entities.addAll(ontology.getEntitiesInSignature(iri)); + } else { + OWLEntity entity; + try { + entity = getEntity(ontology, iri, true); + } catch (Exception e) { + // Can happen if several entities are punned to the same IRI + logger.warn(e.getMessage()); + entity = null; + } + if (entity != null) { + // Do not add null entries + entities.add(entity); + } } } return entities; From 7c1bdf1f3fdb67a2b0917541a16b32d6440f1939 Mon Sep 17 00:00:00 2001 From: Damien Goutte-Gattat Date: Tue, 25 Mar 2025 22:44:26 +0000 Subject: [PATCH 2/3] Document/test the new --allow-punning option. Mention the `--allow-punning` option in the documentation for the `remove` command. Add two test cases based on the UO ontology, which makes an intensive use of punning. --- CHANGELOG.md | 1 + docs/examples/uo_mole_subset.ofn | 183 +++++++++++++++++++ docs/examples/uo_no_micromole.ofn | 171 +++++++++++++++++ docs/examples/uo_no_micromole_individual.ofn | 181 ++++++++++++++++++ docs/remove.md | 21 +++ 5 files changed, 557 insertions(+) create mode 100644 docs/examples/uo_mole_subset.ofn create mode 100644 docs/examples/uo_no_micromole.ofn create mode 100644 docs/examples/uo_no_micromole_individual.ofn diff --git a/CHANGELOG.md b/CHANGELOG.md index fbd6bb01e..0b00c2da3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add `--clean-obo` option to [`convert`] [#995] - Allow interpolation of ontology IRI and version IRI within annotation values [#1241] +- Allow selecting punned entities in [`remove`] and [`filter`] ### Fixed - Update owl-diff dependency for stable ordering and to avoid large string creation [#1227] diff --git a/docs/examples/uo_mole_subset.ofn b/docs/examples/uo_mole_subset.ofn new file mode 100644 index 000000000..dcde33d2a --- /dev/null +++ b/docs/examples/uo_mole_subset.ofn @@ -0,0 +1,183 @@ +Prefix(:=) +Prefix(owl:=) +Prefix(rdf:=) +Prefix(xml:=) +Prefix(xsd:=) +Prefix(rdfs:=) + + +Ontology( + +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(ObjectProperty()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(AnnotationProperty()) +Declaration(AnnotationProperty()) + + + +############################ +# Classes +############################ + +# Class: (unit) + +AnnotationAssertion(rdfs:comment "\"A unit of measurement is a standardized quantity of a physical quality.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "unit") + +# Class: (substance unit) + +AnnotationAssertion(rdfs:comment "\"A unit which is a standardised quantity of an element or compound with uniform composition.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "substance unit") +SubClassOf( ) + +# Class: (mole) + +AnnotationAssertion( "mol") +AnnotationAssertion(rdfs:comment "\"A substance unit which is equal to the amount of substance of a molecular system which contains as many elementary entities as there are atoms in 0.012 kilogram of carbon 12.\" [BIPM:BIPM, NIST:NIST]") +AnnotationAssertion(rdfs:label "mole") +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ) + +# Class: (micromole) + +AnnotationAssertion( "umol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to a millionth of a mol or 10^[-6] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "micromole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (millimole) + +AnnotationAssertion( "mmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to a thousandth of a mol or 10^[-3] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "millimole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (nanomole) + +AnnotationAssertion( "nmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to one thousandth of one millionth of a mole or 10^[-9] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "nanomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (picomole) + +AnnotationAssertion( "pmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-12] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "picomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (femtomole) + +AnnotationAssertion( "fmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-15] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "femtomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (attomole) + +AnnotationAssertion( "amol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-18] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "attomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (prefix) + +AnnotationAssertion(rdfs:label "prefix") + +# Class: (milli) + +AnnotationAssertion( "10^[-3]") +AnnotationAssertion( "m") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of one thousand.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "milli") +SubClassOf( ) + +# Class: (micro) + +AnnotationAssertion( "10^[-6]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -6.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "micro") +SubClassOf( ) + +# Class: (nano) + +AnnotationAssertion( "10^[-9]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -9.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "nano") +SubClassOf( ) + +# Class: (pico) + +AnnotationAssertion( "10^[-12]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -12.\" [GVG:UO]") +AnnotationAssertion(rdfs:label "pico") +SubClassOf( ) + +# Class: (femto) + +AnnotationAssertion( "10^[-15]") +AnnotationAssertion( "f") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -15.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "femto") +SubClassOf( ) + +# Class: (atto) + +AnnotationAssertion( "a") +AnnotationAssertion( "10^[-18]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -18.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "atto") +SubClassOf( ) + +# Class: (mole based unit) + +AnnotationAssertion(rdfs:label "mole based unit") +SubClassOf( ) + + + +) \ No newline at end of file diff --git a/docs/examples/uo_no_micromole.ofn b/docs/examples/uo_no_micromole.ofn new file mode 100644 index 000000000..7b9217c55 --- /dev/null +++ b/docs/examples/uo_no_micromole.ofn @@ -0,0 +1,171 @@ +Prefix(:=) +Prefix(owl:=) +Prefix(rdf:=) +Prefix(xml:=) +Prefix(xsd:=) +Prefix(rdfs:=) + + +Ontology( + +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(ObjectProperty()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(AnnotationProperty()) +Declaration(AnnotationProperty()) + + + +############################ +# Classes +############################ + +# Class: (unit) + +AnnotationAssertion(rdfs:comment "\"A unit of measurement is a standardized quantity of a physical quality.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "unit") + +# Class: (substance unit) + +AnnotationAssertion(rdfs:comment "\"A unit which is a standardised quantity of an element or compound with uniform composition.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "substance unit") +SubClassOf( ) + +# Class: (mole) + +AnnotationAssertion( "mol") +AnnotationAssertion(rdfs:comment "\"A substance unit which is equal to the amount of substance of a molecular system which contains as many elementary entities as there are atoms in 0.012 kilogram of carbon 12.\" [BIPM:BIPM, NIST:NIST]") +AnnotationAssertion(rdfs:label "mole") +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ) + +# Class: (millimole) + +AnnotationAssertion( "mmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to a thousandth of a mol or 10^[-3] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "millimole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (nanomole) + +AnnotationAssertion( "nmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to one thousandth of one millionth of a mole or 10^[-9] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "nanomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (picomole) + +AnnotationAssertion( "pmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-12] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "picomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (femtomole) + +AnnotationAssertion( "fmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-15] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "femtomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (attomole) + +AnnotationAssertion( "amol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-18] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "attomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (prefix) + +AnnotationAssertion(rdfs:label "prefix") + +# Class: (milli) + +AnnotationAssertion( "10^[-3]") +AnnotationAssertion( "m") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of one thousand.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "milli") +SubClassOf( ) + +# Class: (micro) + +AnnotationAssertion( "10^[-6]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -6.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "micro") +SubClassOf( ) + +# Class: (nano) + +AnnotationAssertion( "10^[-9]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -9.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "nano") +SubClassOf( ) + +# Class: (pico) + +AnnotationAssertion( "10^[-12]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -12.\" [GVG:UO]") +AnnotationAssertion(rdfs:label "pico") +SubClassOf( ) + +# Class: (femto) + +AnnotationAssertion( "10^[-15]") +AnnotationAssertion( "f") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -15.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "femto") +SubClassOf( ) + +# Class: (atto) + +AnnotationAssertion( "a") +AnnotationAssertion( "10^[-18]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -18.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "atto") +SubClassOf( ) + +# Class: (mole based unit) + +AnnotationAssertion(rdfs:label "mole based unit") +SubClassOf( ) + + + +) \ No newline at end of file diff --git a/docs/examples/uo_no_micromole_individual.ofn b/docs/examples/uo_no_micromole_individual.ofn new file mode 100644 index 000000000..2d28974b9 --- /dev/null +++ b/docs/examples/uo_no_micromole_individual.ofn @@ -0,0 +1,181 @@ +Prefix(:=) +Prefix(owl:=) +Prefix(rdf:=) +Prefix(xml:=) +Prefix(xsd:=) +Prefix(rdfs:=) + + +Ontology( + +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(ObjectProperty()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(AnnotationProperty()) +Declaration(AnnotationProperty()) + + + +############################ +# Classes +############################ + +# Class: (unit) + +AnnotationAssertion(rdfs:comment "\"A unit of measurement is a standardized quantity of a physical quality.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "unit") + +# Class: (substance unit) + +AnnotationAssertion(rdfs:comment "\"A unit which is a standardised quantity of an element or compound with uniform composition.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "substance unit") +SubClassOf( ) + +# Class: (mole) + +AnnotationAssertion( "mol") +AnnotationAssertion(rdfs:comment "\"A substance unit which is equal to the amount of substance of a molecular system which contains as many elementary entities as there are atoms in 0.012 kilogram of carbon 12.\" [BIPM:BIPM, NIST:NIST]") +AnnotationAssertion(rdfs:label "mole") +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ) + +# Class: (micromole) + +AnnotationAssertion( "umol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to a millionth of a mol or 10^[-6] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "micromole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (millimole) + +AnnotationAssertion( "mmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to a thousandth of a mol or 10^[-3] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "millimole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (nanomole) + +AnnotationAssertion( "nmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to one thousandth of one millionth of a mole or 10^[-9] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "nanomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (picomole) + +AnnotationAssertion( "pmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-12] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "picomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (femtomole) + +AnnotationAssertion( "fmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-15] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "femtomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (attomole) + +AnnotationAssertion( "amol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-18] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "attomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (prefix) + +AnnotationAssertion(rdfs:label "prefix") + +# Class: (milli) + +AnnotationAssertion( "10^[-3]") +AnnotationAssertion( "m") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of one thousand.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "milli") +SubClassOf( ) + +# Class: (micro) + +AnnotationAssertion( "10^[-6]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -6.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "micro") +SubClassOf( ) + +# Class: (nano) + +AnnotationAssertion( "10^[-9]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -9.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "nano") +SubClassOf( ) + +# Class: (pico) + +AnnotationAssertion( "10^[-12]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -12.\" [GVG:UO]") +AnnotationAssertion(rdfs:label "pico") +SubClassOf( ) + +# Class: (femto) + +AnnotationAssertion( "10^[-15]") +AnnotationAssertion( "f") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -15.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "femto") +SubClassOf( ) + +# Class: (atto) + +AnnotationAssertion( "a") +AnnotationAssertion( "10^[-18]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -18.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "atto") +SubClassOf( ) + +# Class: (mole based unit) + +AnnotationAssertion(rdfs:label "mole based unit") +SubClassOf( ) + + + +) \ No newline at end of file diff --git a/docs/remove.md b/docs/remove.md index e7366c94a..628a1f477 100644 --- a/docs/remove.md +++ b/docs/remove.md @@ -56,6 +56,11 @@ Finally `--drop-axiom-annotations` option lets you to specify an annotation prop The `remove` and `filter` operations maintains structural integrity by default: lineage is maintained, and gaps will be filled where classes have been removed. If you wish to *not* preserve the hierarchy, include `--preserve-structure false`. +## Selecting punned entities + +By default, if a single term IRI corresponds to several entities of different types (so-called “punned” entities), the corresponding entities are completely ignored when assembling the initial target set. To force the command to consider punned entities, use the `--allow-punning true`. You may then use a subset selector (see below) to further restrict the removal operation to a specific type of entity. + +For example, if `A` is both a class and an individual, `--term A` will fail to select anything. To select both entities, use `--term A --allow-punning true`. To select only the class `A`, use `--term A --allow-punning true --select classes`.` ## Selectors @@ -239,6 +244,22 @@ Extracts a base module, then removing _all_ `oboInOwl:hasDbXref` annotations on --drop-axiom-annotations oboInOwl:hasDbXref \ --output results/filter_annotations_drop_axioms.owl +Remove all punned entities with the IRI UO:0000039: + + robot remove --input uo_mole_subset.ofn + --allow-punning true + --term UO:0000039 + --output results/uo_no_micromole.ofn + +Remove only the _individual_ UO:0000039, leaving aside the class that has the same IRI (note that here we need to restrict the removal operations to logical and declaration axioms, to avoid removing annotation assertions axioms that apply to both the class and the individual): + + robot remove --input uo_mole_subset.ofn + --allow-punning true + --term UO:0000039 + --select individuals + --axioms "logical Declaration" + --output results/uo_no_micromole_individual.ofn + Remove all `oboInOwl:hasDbXref` annotations, both on entities and on axioms, but without removing the annotated axioms themselves: robot remove --input uberon_module.owl \ From abe2acf5c662c96a6c289f4f189da9705e4c4109 Mon Sep 17 00:00:00 2001 From: Damien Goutte-Gattat Date: Tue, 25 Mar 2025 23:02:56 +0000 Subject: [PATCH 3/3] Add unit test for OntologyHelper#getEntities(). Add a unit test for the new overloading variant of OntologyHelper#getEntities() method, checking that it can return punned entities or not depending of the third parameter. --- .../obolibrary/robot/OntologyHelperTest.java | 20 ++ .../src/test/resources/uo_mole_subset.ofn | 183 ++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 robot-core/src/test/resources/uo_mole_subset.ofn diff --git a/robot-core/src/test/java/org/obolibrary/robot/OntologyHelperTest.java b/robot-core/src/test/java/org/obolibrary/robot/OntologyHelperTest.java index c2d63d6ac..6aabecce8 100644 --- a/robot-core/src/test/java/org/obolibrary/robot/OntologyHelperTest.java +++ b/robot-core/src/test/java/org/obolibrary/robot/OntologyHelperTest.java @@ -1,6 +1,7 @@ package org.obolibrary.robot; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.Collections; @@ -185,4 +186,23 @@ public void testMergeExtraAnnotations() throws IOException { Set expected = Collections.singleton("Test 1 Test one"); assertEquals(expected, actual); } + + /** + * Test selecting punning entities. + * + * @throws IOException on issue loading ontology + */ + @Test + public void testGetPunnedEntities() throws IOException { + OWLOntology ontology = loadOntology("/uo_mole_subset.ofn"); + Set iris = Collections.singleton(IRI.create("http://purl.obolibrary.org/obo/UO_0000039")); + + // No punning, expect empty set + Set entities = OntologyHelper.getEntities(ontology, iris, false); + assertTrue(entities.isEmpty()); + + // Allow punning, expect class + individual + entities = OntologyHelper.getEntities(ontology, iris, true); + assertEquals(2, entities.size()); + } } diff --git a/robot-core/src/test/resources/uo_mole_subset.ofn b/robot-core/src/test/resources/uo_mole_subset.ofn new file mode 100644 index 000000000..dcde33d2a --- /dev/null +++ b/robot-core/src/test/resources/uo_mole_subset.ofn @@ -0,0 +1,183 @@ +Prefix(:=) +Prefix(owl:=) +Prefix(rdf:=) +Prefix(xml:=) +Prefix(xsd:=) +Prefix(rdfs:=) + + +Ontology( + +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(Class()) +Declaration(ObjectProperty()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(NamedIndividual()) +Declaration(AnnotationProperty()) +Declaration(AnnotationProperty()) + + + +############################ +# Classes +############################ + +# Class: (unit) + +AnnotationAssertion(rdfs:comment "\"A unit of measurement is a standardized quantity of a physical quality.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "unit") + +# Class: (substance unit) + +AnnotationAssertion(rdfs:comment "\"A unit which is a standardised quantity of an element or compound with uniform composition.\" [Wikipedia:Wikipedia]") +AnnotationAssertion(rdfs:label "substance unit") +SubClassOf( ) + +# Class: (mole) + +AnnotationAssertion( "mol") +AnnotationAssertion(rdfs:comment "\"A substance unit which is equal to the amount of substance of a molecular system which contains as many elementary entities as there are atoms in 0.012 kilogram of carbon 12.\" [BIPM:BIPM, NIST:NIST]") +AnnotationAssertion(rdfs:label "mole") +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ) + +# Class: (micromole) + +AnnotationAssertion( "umol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to a millionth of a mol or 10^[-6] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "micromole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (millimole) + +AnnotationAssertion( "mmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to a thousandth of a mol or 10^[-3] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "millimole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (nanomole) + +AnnotationAssertion( "nmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to one thousandth of one millionth of a mole or 10^[-9] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "nanomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (picomole) + +AnnotationAssertion( "pmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-12] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "picomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (femtomole) + +AnnotationAssertion( "fmol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-15] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "femtomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (attomole) + +AnnotationAssertion( "amol") +AnnotationAssertion(rdfs:comment "\"A substance unit equal to 10^[-18] mol.\" [NIST:NIST]") +AnnotationAssertion(rdfs:label "attomole") +EquivalentClasses( ObjectIntersectionOf( ObjectSomeValuesFrom( ))) +EquivalentClasses( ObjectOneOf()) +SubClassOf( ) +SubClassOf( ObjectSomeValuesFrom( )) + +# Class: (prefix) + +AnnotationAssertion(rdfs:label "prefix") + +# Class: (milli) + +AnnotationAssertion( "10^[-3]") +AnnotationAssertion( "m") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of one thousand.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "milli") +SubClassOf( ) + +# Class: (micro) + +AnnotationAssertion( "10^[-6]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -6.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "micro") +SubClassOf( ) + +# Class: (nano) + +AnnotationAssertion( "10^[-9]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -9.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "nano") +SubClassOf( ) + +# Class: (pico) + +AnnotationAssertion( "10^[-12]") +AnnotationAssertion( "n") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -12.\" [GVG:UO]") +AnnotationAssertion(rdfs:label "pico") +SubClassOf( ) + +# Class: (femto) + +AnnotationAssertion( "10^[-15]") +AnnotationAssertion( "f") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -15.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "femto") +SubClassOf( ) + +# Class: (atto) + +AnnotationAssertion( "a") +AnnotationAssertion( "10^[-18]") +AnnotationAssertion(rdfs:comment "\"A prefix in the metric system denoting a factor of 10 to the power of -18.\" [UO:GVG]") +AnnotationAssertion(rdfs:label "atto") +SubClassOf( ) + +# Class: (mole based unit) + +AnnotationAssertion(rdfs:label "mole based unit") +SubClassOf( ) + + + +) \ No newline at end of file