Difference between revisions of "BeanShell"
(→Duplicated Axioms) |
|||
(10 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
= The BeanShell = | = The BeanShell = | ||
− | + | __TOC__ | |
− | The beanshell (a CO-ODE plugin developed at the University of Manchester) can fill some of these needs. The primary disadvantage of the bean shell is that it requires some experience with Java and knowledge of the OWL API. This will severely limit the audience but I thought it would still be useful to include some pages on how to use the beanshell. | + | As a Protege developer, I have a unique ability to answer complex questions about large ontologies. All I have to do is to start Protege inside eclipse, open the ontology and set a breakpoint and I will have access to a full array of powerful Java tools for analyzing the ontology. These tools range from the full set of [http://owlapi.sourceforge.net OWL API] features, direct access to reasoners and the ability to make a complex script out of simple primitives. I have often thought that this power would be much more useful in the hands of the end user but it has been unclear how to get there. What is really needed is a very powerful scripting language. |
+ | |||
+ | The beanshell (a CO-ODE plugin developed at the University of Manchester) can fill some of these needs. The primary disadvantage of the bean shell is that it requires some experience with Java and knowledge of the [http://owlapi.sourceforge.net OWL API]. This will severely limit the audience but I thought it would still be useful to include some pages on how to use the beanshell. | ||
The beanshell also requires some understanding of the Protege API but to start with all that is really needed is to know one call: | The beanshell also requires some understanding of the Protege API but to start with all that is really needed is to know one call: | ||
<pre> | <pre> | ||
Line 10: | Line 12: | ||
Here the ''mgnr'' is the Protege Model Manager which keeps track of such things as which ontologies are displayed, how enties in the ontology should be display and the active OWL reasoner. | Here the ''mgnr'' is the Protege Model Manager which keeps track of such things as which ontologies are displayed, how enties in the ontology should be display and the active OWL reasoner. | ||
− | Some documentation for the beanshell can be found [http://code.google.com/p/co-ode-owl-plugins/wiki/BeanshellView here]. My idea in writing this page was to supplement that page with some examples of queries that I have used in my work. I am just starting this page so I will start with a query that is so simple that it could have been done even in a simple language like SPARQL. I will look at properties that are punned with each other. Any such problem represents a problem in the ontology. To make this interesting I will show what happens when I run this script on the [http://xmlns.com/foaf/0.1/ foaf ontology] which is known to have some problems as an OWL 2 file. The script is as follows: | + | Some documentation for the beanshell can be found [http://code.google.com/p/co-ode-owl-plugins/wiki/BeanshellView here]. My idea in writing this page was to supplement that page with some examples of queries that I have used in my work. |
+ | |||
+ | == Property Puns == | ||
+ | |||
+ | I am just starting this page so I will start with a query that is so simple that it could have been done even in a simple language like SPARQL. I will look at properties that are punned with each other. Any such problem represents a problem in the ontology. To make this interesting I will show what happens when I run this script on the [http://xmlns.com/foaf/0.1/ foaf ontology] which is known to have some problems as an OWL 2 file. The script is as follows: | ||
<pre> | <pre> | ||
OWLOntology ontology = mngr.getActiveOntology(); | OWLOntology ontology = mngr.getActiveOntology(); | ||
Line 54: | Line 60: | ||
The data property <http://xmlns.com/foaf/0.1/aimChatID> is also an object property | The data property <http://xmlns.com/foaf/0.1/aimChatID> is also an object property | ||
</pre> | </pre> | ||
− | This is useful information to know about this ontology because each of these puns represents a potential problem for ontologies that import the foaf ontology and are saved in the popular RDF/XML format. | + | This is useful information to know about this ontology because each of these puns represents a potential problem for ontologies that import the foaf ontology and are saved in the popular RDF/XML format. Just to give some notion of the interactive nature of the development of this script, here is a run with some errors that I corrected: |
+ | <pre> | ||
+ | bsh % for (OWLDatatypeProperty dp : ontology.getAnnotationPropertiesInSignature()) { | ||
+ | if (ontology.containsObjectPropertyInSignature(dp.getIRI())) { | ||
+ | print("The data property " + dp.toString() | ||
+ | + " is also an object property"); | ||
+ | } | ||
+ | } | ||
+ | // Error: EvalError: Class: OWLDatatypeProperty not found in namespace : at Line: 1 : in file: <unknown file> : OWLDatatypeProperty | ||
+ | |||
+ | bsh % for (OWLDataProperty dp : ontology.getAnnotationPropertiesInSignature()) { | ||
+ | if (ontology.containsObjectPropertyInSignature(dp.getIRI())) { | ||
+ | print("The data property " + dp.toString() | ||
+ | + " is also an object property"); | ||
+ | } | ||
+ | } | ||
+ | // Error: // Uncaught Exception: for loop iterator variable:dp: null : at Line: 1 : in file: <unknown file> : for ( OWLDataProperty dp : ontology .getAnnotationPropertiesInSignature ( ) ) { | ||
+ | |||
+ | Target exception: java.lang.ClassCastException: Cannot cast uk.ac.manchester.cs.owl.owlapi.OWLAnnotationPropertyImpl to org.semanticweb.owlapi.model.OWLDataProperty | ||
+ | |||
+ | bsh % for (OWLDataProperty dp : ontology.getDataPropertiesInSignature()) { | ||
+ | if (ontology.containsObjectPropertyInSignature(dp.getIRI())) { | ||
+ | print("The data property " + dp.toString() | ||
+ | + " is also an object property"); | ||
+ | } | ||
+ | } | ||
+ | The data property <http://xmlns.com/foaf/0.1/yahooChatID> is also an object property | ||
+ | The data property <http://xmlns.com/foaf/0.1/mbox_sha1sum> is also an object property | ||
+ | The data property <http://xmlns.com/foaf/0.1/jabberID> is also an object property | ||
+ | The data property <http://xmlns.com/foaf/0.1/icqChatID> is also an object property | ||
+ | The data property <http://xmlns.com/foaf/0.1/msnChatID> is also an object property | ||
+ | The data property <http://xmlns.com/foaf/0.1/aimChatID> is also an object property | ||
+ | bsh % | ||
+ | </pre> | ||
+ | It would be better if the bean shell offered some command completion like eclipse and I will see what can be done about this (it might be tricky?). | ||
+ | |||
+ | == Counting With a Reasoner == | ||
+ | |||
+ | This is a problem that came off the list and it is a bit complicated for the bean shell. But it is a good illustration because it uses several things that might be useful. The user wanted to count the individuals in two classes, calculate the percentage of them that are in the second class and then attach the result to a data property assertion. I am not positive exactly what the data property assertion was supposed to look like but I made an example here. The ontology is as follows: | ||
+ | <pre> | ||
+ | Prefix(owl:=<http://www.w3.org/2002/07/owl#>) | ||
+ | Prefix(:=<http://www.semanticweb.org/ontologies/2011/5/furniture#>) | ||
+ | Prefix(Marouns_problem:=<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#>) | ||
+ | |||
+ | Ontology(<http://www.semanticweb.org/ontologies/2011/5/furniture> | ||
+ | |||
+ | EquivalentClasses(Marouns_problem:having_final_value_0 ObjectComplementOf(Marouns_problem:having_final_value_1)) | ||
+ | EquivalentClasses(Marouns_problem:having_final_value_1 | ||
+ | ObjectUnionOf( | ||
+ | ObjectSomeValuesFrom(Marouns_problem:has_mechanism owl:Thing) | ||
+ | ObjectSomeValuesFrom(Marouns_problem:has_protocol owl:Thing) | ||
+ | ObjectSomeValuesFrom(Marouns_problem:has_service owl:Thing))) | ||
+ | |||
+ | ObjectPropertyRange(Marouns_problem:has_mechanism Marouns_problem:mechanism) | ||
+ | ObjectPropertyRange(Marouns_problem:has_protocol Marouns_problem:protocol) | ||
+ | ObjectPropertyRange(Marouns_problem:has_service Marouns_problem:service) | ||
+ | |||
+ | ClassAssertion(Marouns_problem:moderate Marouns_problem:a) | ||
+ | ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_mechanism Marouns_problem:mechanism) Marouns_problem:a) | ||
+ | ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_protocol Marouns_problem:protocol) Marouns_problem:a) | ||
+ | ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_service Marouns_problem:service) Marouns_problem:a) | ||
+ | |||
+ | ClassAssertion(Marouns_problem:moderate :b) | ||
+ | ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_mechanism Marouns_problem:mechanism) :b) | ||
+ | ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_protocol Marouns_problem:protocol) :b) | ||
+ | |||
+ | ClassAssertion(Marouns_problem:moderate :c) | ||
+ | |||
+ | ClassAssertion(Marouns_problem:moderate :d) | ||
+ | ClassAssertion(ObjectExactCardinality(0 Marouns_problem:has_mechanism) :d) | ||
+ | ClassAssertion(ObjectExactCardinality(0 Marouns_problem:has_protocol) :d) | ||
+ | ClassAssertion(ObjectExactCardinality(0 Marouns_problem:has_service) :d) | ||
+ | ) | ||
+ | </pre> | ||
+ | The user wanted to count the number of the individuals that can be inferred to be in either having_final_value_1 or having_final_value_0 and calculate the percentage of those individuals in having_final_value_1. The user then wanted to put the result in some data property assertions (not sure which ones but I implemented something). | ||
+ | |||
+ | I did this with the following bean shell code: | ||
+ | <pre> | ||
+ | import java.util.List; | ||
+ | |||
+ | import org.protege.editor.owl.model.inference.ReasonerStatus; | ||
+ | import org.protege.editor.owl.model.inference.ReasonerUtilities; | ||
+ | |||
+ | import org.semanticweb.owlapi.reasoner.OWLReasoner; | ||
+ | |||
+ | |||
+ | ReasonerUtilities.warnUserIfReasonerIsNotConfigured(eKit.getOWLWorkspace(), mngr.getOWLReasonerManager()); | ||
+ | if (mngr.getOWLReasonerManager().getReasonerStatus() == ReasonerStatus.INITIALIZED) { | ||
+ | print("Starting run"); | ||
+ | /* | ||
+ | * Getting the standard variables (e.g. the ontology, reasoner, ontology manager,... | ||
+ | */ | ||
+ | OWLOntology ontology = mngr.getActiveOntology(); | ||
+ | OWLReasoner reasoner = mngr.getReasoner(); | ||
+ | String NS = "http://www.semanticweb.org/ontologies/2011/5/Marouns_problem"; | ||
+ | OWLOntologyManager manager = mngr.getOWLOntologyManager(); | ||
+ | OWLDataFactory factory = manager.getOWLDataFactory(); | ||
+ | |||
+ | /* | ||
+ | * Getting entities specific to the particular ontology. | ||
+ | * They can be tested with print statements (e.g. print(ontology.containsEntityInSignature(value0));) | ||
+ | */ | ||
+ | OWLClass value0 = factory.getOWLClass(IRI.create(NS + "#having_final_value_0")); | ||
+ | OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); | ||
+ | OWLDataProperty percentageProperty = factory.getOWLDataProperty(IRI.create(NS + "#percentage_having_final_value_1")); | ||
+ | |||
+ | /* | ||
+ | * Core logic | ||
+ | */ | ||
+ | Set value0Individuals = reasoner.getInstances(value0, false).getFlattened(); | ||
+ | Set value1Individuals = reasoner.getInstances(value1, false).getFlattened(); | ||
+ | int count0 = value0Individuals.size(); | ||
+ | int count1 = value1Individuals.size(); | ||
+ | float percentage = 100.0f * ((float) count1) / ((float) (count0 + count1)); | ||
+ | |||
+ | List changes = new ArrayList(); | ||
+ | /* | ||
+ | * Remove existing percentage data property assertions | ||
+ | */ | ||
+ | for (OWLAxiom axiom : ontology.getReferencingAxioms(percentageProperty)) { | ||
+ | if (axiom instanceof OWLDataPropertyAssertionAxiom && | ||
+ | ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { | ||
+ | changes.add(new RemoveAxiom(ontology, axiom)); | ||
+ | } | ||
+ | } | ||
+ | Set individuals = new HashSet(); | ||
+ | individuals.addAll(value0Individuals); | ||
+ | individuals.addAll(value1Individuals); | ||
+ | /* | ||
+ | * Add new percentage data property assertions | ||
+ | */ | ||
+ | for (OWLNamedIndividual i : individuals) { | ||
+ | changes.add(new AddAxiom(ontology, factory.getOWLDataPropertyAssertionAxiom(percentageProperty, i, percentage))); | ||
+ | } | ||
+ | /* | ||
+ | * Apply the changes in a single transaction | ||
+ | */ | ||
+ | manager.applyChanges(changes); | ||
+ | print("Added percentage data property assertions"); | ||
+ | } | ||
+ | </pre> | ||
+ | It would actually have been much easier for me if I wrote this code in eclipse and then transferred the code to the bean shell. There may be use cases where this is actually exactly the right thing to do. But I wanted to demonstrate the bean shell so I did the exercise in the bean shell. The example above has been polished somewhat so I think it is useful to show the original session and show what hunting and pecking was necessary to make it work. This also shows the advantages of developing through scripting. You can see the results of your work as you go. | ||
+ | <pre> | ||
+ | 2.0b4 - by Pat Niemeyer (pat@pat.net) | ||
+ | bsh % import java.util.List; | ||
+ | bsh % mngr.getReasoner(); | ||
+ | bsh % print(mngr.getReasoner()); | ||
+ | org.protege.editor.owl.model.inference.NoOpReasoner@34f07ec4 | ||
+ | bsh % import org.semanticweb.owlapi.reasoner.OWLReasoner; | ||
+ | bsh % OWLOntology ontology = mngr.getActiveOntology(); | ||
+ | bsh % print(ontology); | ||
+ | Ontology(<http://www.semanticweb.org/ontologies/2011/5/furniture> [Axioms: 34] [Logical axioms: 18]) | ||
+ | bsh % OWLReasoner reasoner = mngr.getReasoner(); | ||
+ | bsh % String NS = "http://www.semanticweb.org/ontologies/2011/5/furniture"; | ||
+ | bsh % OWLOntologyManager manager = mngr.getOWLOntologyManager(); | ||
+ | bsh % OWLDataFactory factory = manager.getOWLDataFactory(); | ||
+ | bsh % print(factory); | ||
+ | org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl@3efd2905 | ||
+ | bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1"); | ||
+ | // Error: Parser Error: Parse error at line 1, column 2803. Encountered: ( | ||
+ | bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); | ||
+ | bsh % String NS = "http://www.semanticweb.org/ontologies/2011/5/Marouns_Problem"; | ||
+ | bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); | ||
+ | bsh % print(ontology.containsEntityInSignature(value1)); | ||
+ | false | ||
+ | bsh % print(value1) | ||
+ | ; | ||
+ | <http://www.semanticweb.org/ontologies/2011/5/Marouns_Problem#having_final_value_1> | ||
+ | bsh % String NS = "http://www.semanticweb.org/ontologies/2011/5/Marouns_problem"; | ||
+ | bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); | ||
+ | bsh % print(ontology.containsEntityInSignature(value1)); | ||
+ | true | ||
+ | bsh % OWLClass value0 = factory.getOWLClass(IRI.create(NS + "#having_final_value_0")); | ||
+ | bsh % print(ontology.containsEntityInSignature(value0)); | ||
+ | true | ||
+ | bsh % print(reasoner.getInstances(value1, false)); | ||
+ | Nodeset[Node( <http://www.semanticweb.org/ontologies/2011/5/furniture#b> ), Node( <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a> )] | ||
+ | bsh % print(reasoner.getInstances(value1, false).getFlattened().size()); | ||
+ | 2 | ||
+ | bsh % print(reasoner.getInstances(value0, false).getFlattened().size()); | ||
+ | 1 | ||
+ | bsh % int count1 = reasoner.getInstances(value1, false).getFlattened().size(); | ||
+ | bsh % int count0 = reasoner.getInstances(value0, false).getFlattened().size(); | ||
+ | bsh % float percentage = 100.0f * ((float) count1) / ((float) (count0 + count1)); | ||
+ | bsh % print(percentage); | ||
+ | 66.666664 | ||
+ | bsh % OWLDataProperty percentageProperty = factory.getOWLDataProperty(NS + "#percentage_having_final_value_1"); | ||
+ | // Error: EvalError: Typed variable declaration : Error in method invocation: Method getOWLDataProperty( java.lang.String ) not found in class'org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl' : at Line: 1 : in file: <unknown file> : factory .getOWLDataProperty ( NS + "#percentage_having_final_value_1" ) | ||
+ | |||
+ | bsh % OWLDataProperty percentageProperty = factory.getOWLDataProperty(IRI.create(NS + "#percentage_having_final_value_1")); | ||
+ | bsh % print(ontology.containsEntityInSignature(percentageProperty)); | ||
+ | true | ||
+ | bsh % print(ontology.getDataPropertyAssertionAxioms(percentageProperty)); | ||
+ | // Error: EvalError: Error in method invocation: Method getDataPropertyAssertionAxioms( uk.ac.manchester.cs.owl.owlapi.OWLDataPropertyImpl ) not found in class'uk.ac.manchester.cs.owl.owlapi.OWLOntologyImpl' : at Line: 1 : in file: <unknown file> : ontology .getDataPropertyAssertionAxioms ( percentageProperty ) | ||
+ | |||
+ | bsh % List changes = new ArrayList(); | ||
+ | bsh % manager.applyChanges(changes); | ||
+ | bsh % for (OWLAxiom axiom : ontology.getReferencingAxioms(percentageProperty)) { | ||
+ | if (axiom instanceof OWLDataPropertyAssertionAxiom && ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { | ||
+ | changes.add(new RemoveAxiom(ontology, axiom); | ||
+ | // Error: Parser Error: Parse error at line 1, column 10249. Encountered: ( | ||
+ | bsh % if (axiom instanceof OWLDataPropertyAssertionAxiom && ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { changes.add(new RemoveAxiom(ontology, axiom)); } | ||
+ | ; | ||
+ | bsh % bsh % print(changes); | ||
+ | [] | ||
+ | bsh % Set individuals = new HashSet(); | ||
+ | bsh % individuals.addAll(reasoner.getInstances(value1, false).getFlattened()); | ||
+ | bsh % print(individuals); | ||
+ | [<http://www.semanticweb.org/ontologies/2011/5/furniture#b>, <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a>] | ||
+ | bsh % individuals.addAll(reasoner.getInstances(value0, false).getFlattened()); | ||
+ | bsh % print(individuals); | ||
+ | [<http://www.semanticweb.org/ontologies/2011/5/furniture#b>, <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a>, <http://www.semanticweb.org/ontologies/2011/5/furniture#d>] | ||
+ | bsh % for (OWLNamedIndividual i : individuals) { | ||
+ | changes.add(new AddAxiom(ontology, factory.getOWLDataFactoryAssertionAxiom(i, percentageProperty, percentage))); | ||
+ | } | ||
+ | // Error: EvalError: Error in method invocation: Method getOWLDataFactoryAssertionAxiom( uk.ac.manchester.cs.owl.owlapi.OWLNamedIndividualImpl, uk.ac.manchester.cs.owl.owlapi.OWLDataPropertyImpl, float ) not found in class'org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl' : at Line: 1 : in file: <unknown file> : factory .getOWLDataFactoryAssertionAxiom ( i , percentageProperty , percentage ) | ||
+ | |||
+ | bsh % for (OWLNamedIndividual i : individuals) { | ||
+ | changes.add(new AddAxiom(ontology, factory.getOWLDataFactoryAssertionAxiom(percentageProperty, i, percentage))); | ||
+ | } | ||
+ | // Error: EvalError: Error in method invocation: Method getOWLDataFactoryAssertionAxiom( uk.ac.manchester.cs.owl.owlapi.OWLDataPropertyImpl, uk.ac.manchester.cs.owl.owlapi.OWLNamedIndividualImpl, float ) not found in class'org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl' : at Line: 1 : in file: <unknown file> : factory .getOWLDataFactoryAssertionAxiom ( percentageProperty , i , percentage ) | ||
+ | |||
+ | bsh % for (OWLNamedIndividual i : individuals) { | ||
+ | changes.add(new AddAxiom(ontology, factory.getOWLDataPropertyAssertionAxiom(percentageProperty, i, percentage))); | ||
+ | } | ||
+ | bsh % print (changes); | ||
+ | [ADD AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#b> "66.666664"^^xsd:float), ADD AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a> "66.666664"^^xsd:float), ADD AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#d> "66.666664"^^xsd:float)] | ||
+ | bsh % manager.applyChanges(changes); | ||
+ | bsh % changes.clear(); | ||
+ | bsh % % test the remove method | ||
+ | // Error: Parser Error: Parse error at line 1, column 5785. Encountered: % | ||
+ | bsh % ; test the remove method | ||
+ | bsh % // Error: Parser Error: Parse error at line 1, column 67. Encountered: remove | ||
+ | bsh % for (OWLAxiom axiom : ontology.getReferencingAxioms(percentageProperty)) { | ||
+ | if (axiom instanceof OWLDataPropertyAssertionAxiom && ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { | ||
+ | changes.add(new RemoveAxiom(ontology, axiom)); | ||
+ | } | ||
+ | ; | ||
+ | } | ||
+ | bsh % print (changes); | ||
+ | [REMOVE AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a> "66.666664"^^xsd:float), REMOVE AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#b> "66.666664"^^xsd:float), REMOVE AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#d> "66.666664"^^xsd:float)] | ||
+ | bsh % manager.applyChanges(); | ||
+ | // Error: EvalError: Error in method invocation: Method applyChanges() not found in class'org.protege.owlapi.model.ProtegeOWLOntologyManager' : at Line: 1 : in file: <unknown file> : manager .applyChanges ( ) | ||
+ | |||
+ | bsh % manager.applyChanges(changes); | ||
+ | bsh % | ||
+ | </pre> | ||
+ | |||
+ | == Duplicated Axioms == | ||
+ | |||
+ | At one point there was some discussion about how Protege should handle axioms that are duplicated in more than one location in the imports closure of a ontology. Obviously this led to a desire to find all the duplicated axioms. The [https://obi.svn.sourceforge.net/svnroot/obi/trunk/src/ontology/branches/obi.owl obi ontology] is an interesting ontology in this regard - it has several duplicated axioms. I have added some code to ignore the "external" ontologies because these don't really count for this analysis in the obi case. For some reason this bean shell code only works when it is cut and pasted. It does not work when it is run from a script file. I don't know why yet. Note the use of mngr.getRendering(...) to properly display an axiom. | ||
+ | <pre> | ||
+ | import java.util.TreeSet; | ||
+ | |||
+ | print("Starting algorithm"); | ||
+ | |||
+ | Set allAxioms = new HashSet(); | ||
+ | for (OWLOntology inImportsClosure : mngr.getActiveOntology().getImportsClosure()) { | ||
+ | if (inImportsClosure.getOntologyID().getOntologyIRI().toString().contains("external")) { | ||
+ | continue; | ||
+ | } | ||
+ | print("Getting axioms from " + inImportsClosure); | ||
+ | allAxioms.addAll(inImportsClosure.getAxioms()); | ||
+ | }; | ||
+ | |||
+ | print("Collected " + allAxioms.size() + " from all the ontologies"); | ||
+ | for (OWLAxiom axiom : allAxioms) { | ||
+ | if (axiom instanceof OWLDeclarationAxiom) { | ||
+ | continue; | ||
+ | } | ||
+ | Set ontologies = new TreeSet(); | ||
+ | for (OWLOntology inImportsClosure : mngr.getActiveOntology().getImportsClosure()) { | ||
+ | if (inImportsClosure.getOntologyID().getOntologyIRI().toString().contains("external")) { | ||
+ | continue; | ||
+ | } | ||
+ | if (inImportsClosure.containsAxiom(axiom)) { | ||
+ | ontologies.add(inImportsClosure); | ||
+ | } | ||
+ | } | ||
+ | if (ontologies.size() > 1) { | ||
+ | print("Axiom: " + mngr.getRendering(axiom) + "\nis found in the following ontologies:"); | ||
+ | for (OWLOntology ontology : ontologies) { | ||
+ | print("\t" + ontology); | ||
+ | } | ||
+ | } | ||
+ | }; | ||
+ | </pre> | ||
+ | On one version of obi the output of this script looks as follows: | ||
+ | <pre> | ||
+ | Axiom: Transitive: has_part | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Ontology(<http://www.obofoundry.org/ro/ro.owl> [Axioms: 148] [Logical axioms: 37]) | ||
+ | Axiom: 'editor note' label "editor note"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'definition source' label "definition source"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'metadata complete' Type Thing | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'example to be eventually removed' Type 'curation status specification' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'information content entity' SubClassOf generically_dependent_continuant | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: uncurated Type 'curation status specification' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: definition label "definition"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'pending final vetting' Type 'curation status specification' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: is_concretization_of Domain specifically_dependent_continuant | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'organizational term' Type 'curation status specification' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'information content entity' label "information content entity"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'data item' label "data item"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'has curation status' label "has curation status"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'ready for release' Type 'curation status specification' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'metadata incomplete' Type 'curation status specification' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'failed exploratory term' Type Thing | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Axiom: is_concretized_as InverseOf is_concretization_of | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'metadata complete' Type 'curation status specification' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: <http://code.google.com/p/information-artifact-ontology/> Type Thing | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao.owl> [Axioms: 1] [Logical axioms: 1]) | ||
+ | Axiom: 'has obsolescence reason' label "has obsolescence reason"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: is_concretization_of label "is_concretization_of"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'data item' SubClassOf 'information content entity' | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'imported from' label "imported from"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'example of usage' label "example of usage"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'definition editor' label "definition editor"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: 'alternative term' label "alternative term"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: is_concretized_as label "is_concretized_as"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'editor preferred term' label "editor preferred term"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | Axiom: is_concretized_as Range specifically_dependent_continuant | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) | ||
+ | Axiom: 'in branch' label "in branch"@en | ||
+ | is found in the following ontologies: | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) | ||
+ | Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) | ||
+ | </pre> | ||
+ | |||
+ | == Missing Annotation Properties == | ||
+ | |||
+ | Coming soon... |
Latest revision as of 11:59, June 15, 2011
The BeanShell
Contents
As a Protege developer, I have a unique ability to answer complex questions about large ontologies. All I have to do is to start Protege inside eclipse, open the ontology and set a breakpoint and I will have access to a full array of powerful Java tools for analyzing the ontology. These tools range from the full set of OWL API features, direct access to reasoners and the ability to make a complex script out of simple primitives. I have often thought that this power would be much more useful in the hands of the end user but it has been unclear how to get there. What is really needed is a very powerful scripting language.
The beanshell (a CO-ODE plugin developed at the University of Manchester) can fill some of these needs. The primary disadvantage of the bean shell is that it requires some experience with Java and knowledge of the OWL API. This will severely limit the audience but I thought it would still be useful to include some pages on how to use the beanshell. The beanshell also requires some understanding of the Protege API but to start with all that is really needed is to know one call:
ontology = mngr.getActiveOntology();
Here the mgnr is the Protege Model Manager which keeps track of such things as which ontologies are displayed, how enties in the ontology should be display and the active OWL reasoner.
Some documentation for the beanshell can be found here. My idea in writing this page was to supplement that page with some examples of queries that I have used in my work.
Property Puns
I am just starting this page so I will start with a query that is so simple that it could have been done even in a simple language like SPARQL. I will look at properties that are punned with each other. Any such problem represents a problem in the ontology. To make this interesting I will show what happens when I run this script on the foaf ontology which is known to have some problems as an OWL 2 file. The script is as follows:
OWLOntology ontology = mngr.getActiveOntology(); print("\nActive Ontology = " + ontology); for (OWLAnnotationProperty ap : ontology.getAnnotationPropertiesInSignature()) { if (ontology.containsDataPropertyInSignature(ap.getIRI())) { print("The annotation property " + ap.toString() + " is also a data property"); } } for (OWLAnnotationProperty ap : ontology.getAnnotationPropertiesInSignature()) { if (ontology.containsObjectPropertyInSignature(ap.getIRI())) { print("The Annotation Property " + ap.toString() + " is also an object property"); } } for (OWLDataProperty dp : ontology.getDataPropertiesInSignature()) { if (ontology.containsObjectPropertyInSignature(dp.getIRI())) { print("The data property " + dp.toString() + " is also an object property"); } }
This script can either be run interactively:
bsh % ontology = mngr.getActiveOntology(); bsh % print(ontology); Ontology(<http://xmlns.com/foaf/0.1/> [Axioms: 550] [Logical axioms: 157]) bsh %
or by being copied into a file and then run with the Run script command. The output looks like this:
Active Ontology = Ontology(<http://xmlns.com/foaf/0.1/> [Axioms: 550] [Logical axioms: 157]) The annotation property <http://xmlns.com/foaf/0.1/name> is also a data property The data property <http://xmlns.com/foaf/0.1/yahooChatID> is also an object property The data property <http://xmlns.com/foaf/0.1/mbox_sha1sum> is also an object property The data property <http://xmlns.com/foaf/0.1/jabberID> is also an object property The data property <http://xmlns.com/foaf/0.1/icqChatID> is also an object property The data property <http://xmlns.com/foaf/0.1/msnChatID> is also an object property The data property <http://xmlns.com/foaf/0.1/aimChatID> is also an object property
This is useful information to know about this ontology because each of these puns represents a potential problem for ontologies that import the foaf ontology and are saved in the popular RDF/XML format. Just to give some notion of the interactive nature of the development of this script, here is a run with some errors that I corrected:
bsh % for (OWLDatatypeProperty dp : ontology.getAnnotationPropertiesInSignature()) { if (ontology.containsObjectPropertyInSignature(dp.getIRI())) { print("The data property " + dp.toString() + " is also an object property"); } } // Error: EvalError: Class: OWLDatatypeProperty not found in namespace : at Line: 1 : in file: <unknown file> : OWLDatatypeProperty bsh % for (OWLDataProperty dp : ontology.getAnnotationPropertiesInSignature()) { if (ontology.containsObjectPropertyInSignature(dp.getIRI())) { print("The data property " + dp.toString() + " is also an object property"); } } // Error: // Uncaught Exception: for loop iterator variable:dp: null : at Line: 1 : in file: <unknown file> : for ( OWLDataProperty dp : ontology .getAnnotationPropertiesInSignature ( ) ) { Target exception: java.lang.ClassCastException: Cannot cast uk.ac.manchester.cs.owl.owlapi.OWLAnnotationPropertyImpl to org.semanticweb.owlapi.model.OWLDataProperty bsh % for (OWLDataProperty dp : ontology.getDataPropertiesInSignature()) { if (ontology.containsObjectPropertyInSignature(dp.getIRI())) { print("The data property " + dp.toString() + " is also an object property"); } } The data property <http://xmlns.com/foaf/0.1/yahooChatID> is also an object property The data property <http://xmlns.com/foaf/0.1/mbox_sha1sum> is also an object property The data property <http://xmlns.com/foaf/0.1/jabberID> is also an object property The data property <http://xmlns.com/foaf/0.1/icqChatID> is also an object property The data property <http://xmlns.com/foaf/0.1/msnChatID> is also an object property The data property <http://xmlns.com/foaf/0.1/aimChatID> is also an object property bsh %
It would be better if the bean shell offered some command completion like eclipse and I will see what can be done about this (it might be tricky?).
Counting With a Reasoner
This is a problem that came off the list and it is a bit complicated for the bean shell. But it is a good illustration because it uses several things that might be useful. The user wanted to count the individuals in two classes, calculate the percentage of them that are in the second class and then attach the result to a data property assertion. I am not positive exactly what the data property assertion was supposed to look like but I made an example here. The ontology is as follows:
Prefix(owl:=<http://www.w3.org/2002/07/owl#>) Prefix(:=<http://www.semanticweb.org/ontologies/2011/5/furniture#>) Prefix(Marouns_problem:=<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#>) Ontology(<http://www.semanticweb.org/ontologies/2011/5/furniture> EquivalentClasses(Marouns_problem:having_final_value_0 ObjectComplementOf(Marouns_problem:having_final_value_1)) EquivalentClasses(Marouns_problem:having_final_value_1 ObjectUnionOf( ObjectSomeValuesFrom(Marouns_problem:has_mechanism owl:Thing) ObjectSomeValuesFrom(Marouns_problem:has_protocol owl:Thing) ObjectSomeValuesFrom(Marouns_problem:has_service owl:Thing))) ObjectPropertyRange(Marouns_problem:has_mechanism Marouns_problem:mechanism) ObjectPropertyRange(Marouns_problem:has_protocol Marouns_problem:protocol) ObjectPropertyRange(Marouns_problem:has_service Marouns_problem:service) ClassAssertion(Marouns_problem:moderate Marouns_problem:a) ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_mechanism Marouns_problem:mechanism) Marouns_problem:a) ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_protocol Marouns_problem:protocol) Marouns_problem:a) ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_service Marouns_problem:service) Marouns_problem:a) ClassAssertion(Marouns_problem:moderate :b) ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_mechanism Marouns_problem:mechanism) :b) ClassAssertion(ObjectExactCardinality(1 Marouns_problem:has_protocol Marouns_problem:protocol) :b) ClassAssertion(Marouns_problem:moderate :c) ClassAssertion(Marouns_problem:moderate :d) ClassAssertion(ObjectExactCardinality(0 Marouns_problem:has_mechanism) :d) ClassAssertion(ObjectExactCardinality(0 Marouns_problem:has_protocol) :d) ClassAssertion(ObjectExactCardinality(0 Marouns_problem:has_service) :d) )
The user wanted to count the number of the individuals that can be inferred to be in either having_final_value_1 or having_final_value_0 and calculate the percentage of those individuals in having_final_value_1. The user then wanted to put the result in some data property assertions (not sure which ones but I implemented something).
I did this with the following bean shell code:
import java.util.List; import org.protege.editor.owl.model.inference.ReasonerStatus; import org.protege.editor.owl.model.inference.ReasonerUtilities; import org.semanticweb.owlapi.reasoner.OWLReasoner; ReasonerUtilities.warnUserIfReasonerIsNotConfigured(eKit.getOWLWorkspace(), mngr.getOWLReasonerManager()); if (mngr.getOWLReasonerManager().getReasonerStatus() == ReasonerStatus.INITIALIZED) { print("Starting run"); /* * Getting the standard variables (e.g. the ontology, reasoner, ontology manager,... */ OWLOntology ontology = mngr.getActiveOntology(); OWLReasoner reasoner = mngr.getReasoner(); String NS = "http://www.semanticweb.org/ontologies/2011/5/Marouns_problem"; OWLOntologyManager manager = mngr.getOWLOntologyManager(); OWLDataFactory factory = manager.getOWLDataFactory(); /* * Getting entities specific to the particular ontology. * They can be tested with print statements (e.g. print(ontology.containsEntityInSignature(value0));) */ OWLClass value0 = factory.getOWLClass(IRI.create(NS + "#having_final_value_0")); OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); OWLDataProperty percentageProperty = factory.getOWLDataProperty(IRI.create(NS + "#percentage_having_final_value_1")); /* * Core logic */ Set value0Individuals = reasoner.getInstances(value0, false).getFlattened(); Set value1Individuals = reasoner.getInstances(value1, false).getFlattened(); int count0 = value0Individuals.size(); int count1 = value1Individuals.size(); float percentage = 100.0f * ((float) count1) / ((float) (count0 + count1)); List changes = new ArrayList(); /* * Remove existing percentage data property assertions */ for (OWLAxiom axiom : ontology.getReferencingAxioms(percentageProperty)) { if (axiom instanceof OWLDataPropertyAssertionAxiom && ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { changes.add(new RemoveAxiom(ontology, axiom)); } } Set individuals = new HashSet(); individuals.addAll(value0Individuals); individuals.addAll(value1Individuals); /* * Add new percentage data property assertions */ for (OWLNamedIndividual i : individuals) { changes.add(new AddAxiom(ontology, factory.getOWLDataPropertyAssertionAxiom(percentageProperty, i, percentage))); } /* * Apply the changes in a single transaction */ manager.applyChanges(changes); print("Added percentage data property assertions"); }
It would actually have been much easier for me if I wrote this code in eclipse and then transferred the code to the bean shell. There may be use cases where this is actually exactly the right thing to do. But I wanted to demonstrate the bean shell so I did the exercise in the bean shell. The example above has been polished somewhat so I think it is useful to show the original session and show what hunting and pecking was necessary to make it work. This also shows the advantages of developing through scripting. You can see the results of your work as you go.
2.0b4 - by Pat Niemeyer (pat@pat.net) bsh % import java.util.List; bsh % mngr.getReasoner(); bsh % print(mngr.getReasoner()); org.protege.editor.owl.model.inference.NoOpReasoner@34f07ec4 bsh % import org.semanticweb.owlapi.reasoner.OWLReasoner; bsh % OWLOntology ontology = mngr.getActiveOntology(); bsh % print(ontology); Ontology(<http://www.semanticweb.org/ontologies/2011/5/furniture> [Axioms: 34] [Logical axioms: 18]) bsh % OWLReasoner reasoner = mngr.getReasoner(); bsh % String NS = "http://www.semanticweb.org/ontologies/2011/5/furniture"; bsh % OWLOntologyManager manager = mngr.getOWLOntologyManager(); bsh % OWLDataFactory factory = manager.getOWLDataFactory(); bsh % print(factory); org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl@3efd2905 bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1"); // Error: Parser Error: Parse error at line 1, column 2803. Encountered: ( bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); bsh % String NS = "http://www.semanticweb.org/ontologies/2011/5/Marouns_Problem"; bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); bsh % print(ontology.containsEntityInSignature(value1)); false bsh % print(value1) ; <http://www.semanticweb.org/ontologies/2011/5/Marouns_Problem#having_final_value_1> bsh % String NS = "http://www.semanticweb.org/ontologies/2011/5/Marouns_problem"; bsh % OWLClass value1 = factory.getOWLClass(IRI.create(NS + "#having_final_value_1")); bsh % print(ontology.containsEntityInSignature(value1)); true bsh % OWLClass value0 = factory.getOWLClass(IRI.create(NS + "#having_final_value_0")); bsh % print(ontology.containsEntityInSignature(value0)); true bsh % print(reasoner.getInstances(value1, false)); Nodeset[Node( <http://www.semanticweb.org/ontologies/2011/5/furniture#b> ), Node( <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a> )] bsh % print(reasoner.getInstances(value1, false).getFlattened().size()); 2 bsh % print(reasoner.getInstances(value0, false).getFlattened().size()); 1 bsh % int count1 = reasoner.getInstances(value1, false).getFlattened().size(); bsh % int count0 = reasoner.getInstances(value0, false).getFlattened().size(); bsh % float percentage = 100.0f * ((float) count1) / ((float) (count0 + count1)); bsh % print(percentage); 66.666664 bsh % OWLDataProperty percentageProperty = factory.getOWLDataProperty(NS + "#percentage_having_final_value_1"); // Error: EvalError: Typed variable declaration : Error in method invocation: Method getOWLDataProperty( java.lang.String ) not found in class'org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl' : at Line: 1 : in file: <unknown file> : factory .getOWLDataProperty ( NS + "#percentage_having_final_value_1" ) bsh % OWLDataProperty percentageProperty = factory.getOWLDataProperty(IRI.create(NS + "#percentage_having_final_value_1")); bsh % print(ontology.containsEntityInSignature(percentageProperty)); true bsh % print(ontology.getDataPropertyAssertionAxioms(percentageProperty)); // Error: EvalError: Error in method invocation: Method getDataPropertyAssertionAxioms( uk.ac.manchester.cs.owl.owlapi.OWLDataPropertyImpl ) not found in class'uk.ac.manchester.cs.owl.owlapi.OWLOntologyImpl' : at Line: 1 : in file: <unknown file> : ontology .getDataPropertyAssertionAxioms ( percentageProperty ) bsh % List changes = new ArrayList(); bsh % manager.applyChanges(changes); bsh % for (OWLAxiom axiom : ontology.getReferencingAxioms(percentageProperty)) { if (axiom instanceof OWLDataPropertyAssertionAxiom && ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { changes.add(new RemoveAxiom(ontology, axiom); // Error: Parser Error: Parse error at line 1, column 10249. Encountered: ( bsh % if (axiom instanceof OWLDataPropertyAssertionAxiom && ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { changes.add(new RemoveAxiom(ontology, axiom)); } ; bsh % bsh % print(changes); [] bsh % Set individuals = new HashSet(); bsh % individuals.addAll(reasoner.getInstances(value1, false).getFlattened()); bsh % print(individuals); [<http://www.semanticweb.org/ontologies/2011/5/furniture#b>, <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a>] bsh % individuals.addAll(reasoner.getInstances(value0, false).getFlattened()); bsh % print(individuals); [<http://www.semanticweb.org/ontologies/2011/5/furniture#b>, <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a>, <http://www.semanticweb.org/ontologies/2011/5/furniture#d>] bsh % for (OWLNamedIndividual i : individuals) { changes.add(new AddAxiom(ontology, factory.getOWLDataFactoryAssertionAxiom(i, percentageProperty, percentage))); } // Error: EvalError: Error in method invocation: Method getOWLDataFactoryAssertionAxiom( uk.ac.manchester.cs.owl.owlapi.OWLNamedIndividualImpl, uk.ac.manchester.cs.owl.owlapi.OWLDataPropertyImpl, float ) not found in class'org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl' : at Line: 1 : in file: <unknown file> : factory .getOWLDataFactoryAssertionAxiom ( i , percentageProperty , percentage ) bsh % for (OWLNamedIndividual i : individuals) { changes.add(new AddAxiom(ontology, factory.getOWLDataFactoryAssertionAxiom(percentageProperty, i, percentage))); } // Error: EvalError: Error in method invocation: Method getOWLDataFactoryAssertionAxiom( uk.ac.manchester.cs.owl.owlapi.OWLDataPropertyImpl, uk.ac.manchester.cs.owl.owlapi.OWLNamedIndividualImpl, float ) not found in class'org.protege.owlapi.concurrent.SynchronizedOWLDataFactoryImpl' : at Line: 1 : in file: <unknown file> : factory .getOWLDataFactoryAssertionAxiom ( percentageProperty , i , percentage ) bsh % for (OWLNamedIndividual i : individuals) { changes.add(new AddAxiom(ontology, factory.getOWLDataPropertyAssertionAxiom(percentageProperty, i, percentage))); } bsh % print (changes); [ADD AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#b> "66.666664"^^xsd:float), ADD AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a> "66.666664"^^xsd:float), ADD AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#d> "66.666664"^^xsd:float)] bsh % manager.applyChanges(changes); bsh % changes.clear(); bsh % % test the remove method // Error: Parser Error: Parse error at line 1, column 5785. Encountered: % bsh % ; test the remove method bsh % // Error: Parser Error: Parse error at line 1, column 67. Encountered: remove bsh % for (OWLAxiom axiom : ontology.getReferencingAxioms(percentageProperty)) { if (axiom instanceof OWLDataPropertyAssertionAxiom && ((OWLDataPropertyAssertionAxiom) axiom).getProperty().equals(percentageProperty)) { changes.add(new RemoveAxiom(ontology, axiom)); } ; } bsh % print (changes); [REMOVE AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#a> "66.666664"^^xsd:float), REMOVE AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#b> "66.666664"^^xsd:float), REMOVE AXIOM: DataPropertyAssertion(<http://www.semanticweb.org/ontologies/2011/5/Marouns_problem#percentage_having_final_value_1> <http://www.semanticweb.org/ontologies/2011/5/furniture#d> "66.666664"^^xsd:float)] bsh % manager.applyChanges(); // Error: EvalError: Error in method invocation: Method applyChanges() not found in class'org.protege.owlapi.model.ProtegeOWLOntologyManager' : at Line: 1 : in file: <unknown file> : manager .applyChanges ( ) bsh % manager.applyChanges(changes); bsh %
Duplicated Axioms
At one point there was some discussion about how Protege should handle axioms that are duplicated in more than one location in the imports closure of a ontology. Obviously this led to a desire to find all the duplicated axioms. The obi ontology is an interesting ontology in this regard - it has several duplicated axioms. I have added some code to ignore the "external" ontologies because these don't really count for this analysis in the obi case. For some reason this bean shell code only works when it is cut and pasted. It does not work when it is run from a script file. I don't know why yet. Note the use of mngr.getRendering(...) to properly display an axiom.
import java.util.TreeSet; print("Starting algorithm"); Set allAxioms = new HashSet(); for (OWLOntology inImportsClosure : mngr.getActiveOntology().getImportsClosure()) { if (inImportsClosure.getOntologyID().getOntologyIRI().toString().contains("external")) { continue; } print("Getting axioms from " + inImportsClosure); allAxioms.addAll(inImportsClosure.getAxioms()); }; print("Collected " + allAxioms.size() + " from all the ontologies"); for (OWLAxiom axiom : allAxioms) { if (axiom instanceof OWLDeclarationAxiom) { continue; } Set ontologies = new TreeSet(); for (OWLOntology inImportsClosure : mngr.getActiveOntology().getImportsClosure()) { if (inImportsClosure.getOntologyID().getOntologyIRI().toString().contains("external")) { continue; } if (inImportsClosure.containsAxiom(axiom)) { ontologies.add(inImportsClosure); } } if (ontologies.size() > 1) { print("Axiom: " + mngr.getRendering(axiom) + "\nis found in the following ontologies:"); for (OWLOntology ontology : ontologies) { print("\t" + ontology); } } };
On one version of obi the output of this script looks as follows:
Axiom: Transitive: has_part is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Ontology(<http://www.obofoundry.org/ro/ro.owl> [Axioms: 148] [Logical axioms: 37]) Axiom: 'editor note' label "editor note"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'definition source' label "definition source"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'metadata complete' Type Thing is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'example to be eventually removed' Type 'curation status specification' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'information content entity' SubClassOf generically_dependent_continuant is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: uncurated Type 'curation status specification' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: definition label "definition"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'pending final vetting' Type 'curation status specification' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: is_concretization_of Domain specifically_dependent_continuant is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'organizational term' Type 'curation status specification' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'information content entity' label "information content entity"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'data item' label "data item"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'has curation status' label "has curation status"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'ready for release' Type 'curation status specification' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'metadata incomplete' Type 'curation status specification' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'failed exploratory term' Type Thing is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Axiom: is_concretized_as InverseOf is_concretization_of is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'metadata complete' Type 'curation status specification' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: <http://code.google.com/p/information-artifact-ontology/> Type Thing is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao.owl> [Axioms: 1] [Logical axioms: 1]) Axiom: 'has obsolescence reason' label "has obsolescence reason"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: is_concretization_of label "is_concretization_of"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'data item' SubClassOf 'information content entity' is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'imported from' label "imported from"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'example of usage' label "example of usage"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'definition editor' label "definition editor"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: 'alternative term' label "alternative term"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: is_concretized_as label "is_concretized_as"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'editor preferred term' label "editor preferred term"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37]) Axiom: is_concretized_as Range specifically_dependent_continuant is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/obi.owl> [Axioms: 18680] [Logical axioms: 3560]) Axiom: 'in branch' label "in branch"@en is found in the following ontologies: Ontology(<http://purl.obolibrary.org/obo/iao/dev/iao-main.owl> [Axioms: 1084] [Logical axioms: 173]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/obsolete.owl> [Axioms: 204] [Logical axioms: 21]) Ontology(<http://purl.obolibrary.org/obo/iao/dev/ontology-metadata.owl> [Axioms: 243] [Logical axioms: 37])
Missing Annotation Properties
Coming soon...