Repository: ontodev/robot (java)

Issue:
StackOverflowError with "robot remove"
I tried to remove a BFO class from PATO with `robot remove --input pato.owl --term BFO:0000023 --select 'self descendants' --signature true --output pato_removed.owl`
 but this fails with:
```
Exception in thread "main" java.lang.StackOverflowError
	at java.base/java.util.HashMap.putVal(HashMap.java:624)
	at java.base/java.util.HashMap.put(HashMap.java:607)
	at java.base/java.util.HashSet.add(HashSet.java:220)
	at java.base/java.util.AbstractCollection.addAll(AbstractCollection.java:352)
	at com.google.common.collect.Iterables.addAll(Iterables.java:352)
	at uk.ac.manchester.cs.owl.owlapi.OWLImmutableOntologyImpl.asSet(OWLImmutableOntologyImpl.java:805)
	at uk.ac.manchester.cs.owl.owlapi.OWLImmutableOntologyImpl.getAxioms(OWLImmutableOntologyImpl.java:1325)
	at uk.ac.manchester.cs.owl.owlapi.OWLAxiomIndexImpl.getSubClassAxiomsForSuperClass(OWLAxiomIndexImpl.java:142)
	at uk.ac.manchester.cs.owl.owlapi.concurrent.ConcurrentOWLOntologyImpl.getSubClassAxiomsForSuperClass(ConcurrentOWLOntologyImpl.java:1779)
	at org.semanticweb.owlapi.search.EntitySearcher.getSubClasses(EntitySearcher.java:839)
	at org.obolibrary.robot.RelatedObjectsHelper.selectClassDescendants(RelatedObjectsHelper.java:2055)
	at org.obolibrary.robot.RelatedObjectsHelper.selectClassDescendants(RelatedObjectsHelper.java:2060)
```

ROBOT version 1.8.3

My assumption is that there are recursive axioms between ChEBI:50906 and BFO:0000023 (equivalence and subclass)

It works when I first remove the chebi role
`robot remove --input pato.owl --term CHEBI:50906 --select "self" --signature true --output pato_removed1.owl
`And afterwards remove all the other things from the result of the first step:
`robot remove --input pato_removed1.owl --term BFO:0000023 --select "self descendants" --signature true --output pato_removed.owl
`

Structure around "role" in PATO:
<img width="184" alt="Screenshot 2022-03-14 at 10 35 53" src="https://user-images.githubusercontent.com/5172897/158145176-74e2ee60-b424-4178-92c8-0b587c395d74.png">



Pull request description:
Handle subclass of cycles in related object selections
Resolves #976

- [ ] `docs/` have been added/updated
- [x] tests have been added/updated
- [x] `mvn verify` says all tests pass
- [x] `mvn site` says all JavaDocs correct
- [x] `CHANGELOG.md` has been updated

Break out of recursion in selecting ancestors/descendants if an object is already in the set. This makes sure that if a class is asserted to be both equivalent to and a subclass of another class (see BFO role/CHEBI role in PATO example), we won't get stuck in an infinite loop.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31b437b0..279d07ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,8 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 ## [Unreleased]
+
+### Changed
 - Sort [`report`] violations by rule name within level [#955]
 
+### Fixed
+- Fix subClassOf cycles in related object selection [#979]
+
 ## [1.8.3] - 2021-12-16
 
 ### Changed
@@ -294,6 +299,7 @@ First official release of ROBOT!
 [`template`]: http://robot.obolibrary.org/template
 [`validate`]: http://robot.obolibrary.org/validate
 
+[#979]: https://github.com/ontodev/robot/pull/979
 [#955]: https://github.com/ontodev/robot/pull/955
 [#953]: https://github.com/ontodev/robot/pull/953
 [#951]: https://github.com/ontodev/robot/pull/951
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 28650abf..cbed28d4 100644
--- a/robot-core/src/main/java/org/obolibrary/robot/RelatedObjectsHelper.java
+++ b/robot-core/src/main/java/org/obolibrary/robot/RelatedObjectsHelper.java
@@ -2032,6 +2032,10 @@ public class RelatedObjectsHelper {
     for (OWLClassExpression classExpression : EntitySearcher.getSuperClasses(cls, ontology)) {
       if (!classExpression.isAnonymous()) {
         OWLClass superClass = classExpression.asOWLClass();
+        if (ancestors.contains(superClass)) {
+          // Subclass of/equivalent class can cause a loop - see #976
+          continue;
+        }
         ancestors.add(superClass);
         if (!superClass.isTopEntity()) {
           selectClassAncestors(ontology, superClass, ancestors);
@@ -2055,6 +2059,10 @@ public class RelatedObjectsHelper {
     for (OWLClassExpression classExpression : EntitySearcher.getSubClasses(cls, ontology)) {
       if (!classExpression.isAnonymous()) {
         OWLClass subClass = classExpression.asOWLClass();
+        if (descendants.contains(subClass)) {
+          // Subclass of/equivalent class can cause a loop - see #976
+          continue;
+        }
         descendants.add(subClass);
         if (!EntitySearcher.getSubClasses(subClass, ontology).isEmpty()) {
           selectClassDescendants(ontology, subClass, descendants);


Test patch:
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 5cc46afc..e193ea63 100644
--- a/robot-core/src/test/java/org/obolibrary/robot/RelatedObjectsHelperTest.java
+++ b/robot-core/src/test/java/org/obolibrary/robot/RelatedObjectsHelperTest.java
@@ -4,6 +4,8 @@ import static org.junit.Assert.*;
 
 import com.google.common.collect.Sets;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 import org.junit.Test;
@@ -151,6 +153,29 @@ public class RelatedObjectsHelperTest extends CoreTest {
     assertTrue(annotations.contains(annotation2));
   }
 
+  /**
+   * Test selecting ancestors and descendants with a subClassOf cycle.
+   *
+   * @throws Exception on any problem
+   */
+  @Test
+  public void testSelectCycle() throws Exception {
+    IOHelper ioHelper = new IOHelper();
+    OWLOntology patoRole = loadOntology("/pato_role.owl");
+
+    // Use BFO role as our starting object - then get all ancestors and descendants
+    Set<OWLObject> objects =
+        new HashSet<>(
+            Collections.singletonList(
+                df.getOWLClass(IRI.create("http://purl.obolibrary.org/obo/BFO_0000023"))));
+    Set<OWLObject> relatedObjects =
+        RelatedObjectsHelper.select(
+            patoRole, ioHelper, objects, Arrays.asList("ancestors", "descendants"));
+
+    // Check that the select returned all classes in this ontology (all descendants of role)
+    assert relatedObjects.size() == patoRole.getClassesInSignature().size();
+  }
+
   /** @throws Exception */
   private OWLOntology getOntology() throws Exception {
     OWLOntology ontology = manager.createOntology();
diff --git a/robot-core/src/test/resources/pato_role.owl b/robot-core/src/test/resources/pato_role.owl
new file mode 100644
index 00000000..57449c0f
--- /dev/null
+++ b/robot-core/src/test/resources/pato_role.owl
@@ -0,0 +1,733 @@
+<?xml version="1.0"?>
+<rdf:RDF xmlns="http://purl.obolibrary.org/obo/pato.owl#"
+     xml:base="http://purl.obolibrary.org/obo/pato.owl"
+     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://purl.obolibrary.org/obo/pato.owl"/>
+    
+
+
+    <!-- 
+    ///////////////////////////////////////////////////////////////////////////////////////
+    //
+    // Classes
+    //
+    ///////////////////////////////////////////////////////////////////////////////////////
+     -->
+
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/BFO_0000023 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/BFO_0000023">
+        <owl:equivalentClass rdf:resource="http://purl.obolibrary.org/obo/CHEBI_50906"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_50906"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_138103 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_138103">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_39141"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_15339 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_15339">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_51086"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_17891 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_17891">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_51086"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_22695 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_22695">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_51086"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_23357 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_23357">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52206"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_23888 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_23888">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52217"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_23924 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_23924">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_35222"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52206"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_24432 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_24432">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_50906"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_24621 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_24621">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33280"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_48705"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_25212 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_25212">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52206"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_25512 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_25512">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33280"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_27027 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_27027">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33284"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33232 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33232">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_50906"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33280 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33280">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33281 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33281">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33284 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33284">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_78295"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33286 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33286">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33232"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33287 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33287">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33286"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33893 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33893">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33232"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_33937 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_33937">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33284"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35222 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35222">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35223 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35223">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_51086"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35472 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35472">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_23888"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_67079"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35522 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35522">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_37886"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_48540"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35524 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35524">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_37962"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35554 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35554">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_23888"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35620 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35620">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_35554"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_35942 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_35942">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_23888"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52210"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_37527 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_37527">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_51086"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_37886 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_37886">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_37962"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_37962 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_37962">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_35942"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_38147 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_38147">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_35554"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_38323 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_38323">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_35942"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_38324 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_38324">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_38323"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_38325 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_38325">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_38324"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_39141 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_39141">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_17891"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_37527"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_39142 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_39142">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_15339"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_22695"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_39144 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_39144">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_17891"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_22695"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_46787 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_46787">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33232"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_51086"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_48354 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_48354">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_46787"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_48356 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_48356">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_39141"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_48354"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_48540 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_48540">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_37962"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_48560 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_48560">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_35942"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_48705 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_48705">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52210"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_50906 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_50906">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_50910 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_50910">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52209"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_64909"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_51086 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_51086">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/BFO_0000023"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_50906"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_52206 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_52206">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_52209 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_52209">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_52210 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_52210">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_52211 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_52211">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_52217 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_52217">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33232"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_59740 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_59740">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33893"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_39144"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_63248 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_63248">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_51086"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_64047 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_64047">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33232"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_78295"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_64049 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_64049">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_64047"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_64909 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_64909">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_24432"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_65255 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_65255">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_64047"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_65256 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_65256">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33281"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_65255"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_67079 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_67079">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33232"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_75763 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_75763">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_25212"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_75767 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_75767">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75763"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_75768 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_75768">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75767"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_75771 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_75771">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75768"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_75772 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_75772">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_76946"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_75787 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_75787">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_25212"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76206 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76206">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_25212"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76759 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76759">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_23924"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76764 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76764">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_76759"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76807 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76807">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_76764"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76924 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76924">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75763"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76946 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76946">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75763"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76967 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76967">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_76206"/>
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_77746"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76969 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76969">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75787"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_76971 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_76971">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_76969"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_77746 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_77746">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75768"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_77941 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_77941">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_76807"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_77974 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_77974">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_64047"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_78295 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_78295">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_52211"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_78433 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_78433">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_33232"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_78675 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_78675">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_25212"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_83039 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_83039">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75767"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_83056 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_83056">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_83057"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_83057 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_83057">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_83039"/>
+    </owl:Class>
+    
+
+
+    <!-- http://purl.obolibrary.org/obo/CHEBI_84735 -->
+
+    <owl:Class rdf:about="http://purl.obolibrary.org/obo/CHEBI_84735">
+        <rdfs:subClassOf rdf:resource="http://purl.obolibrary.org/obo/CHEBI_75763"/>
+    </owl:Class>
+</rdf:RDF>
+
+
+
+<!-- Generated by the OWL API (version 4.5.6) https://github.com/owlcs/owlapi -->
+