Some More Basics About Ontology Components
We began looking at managing classes in our last installment of the Cooking with Python and KBpedia series. We continue on that quest in this current installment, expanding our basic commands for instances, data and object properties, annotations, property relations, and operators. We do not probe all available methods, but emphasize those most often encountered. See the Additional Documentation sources at the end of this installment to get further information.
This present installment, plus the prior one, will complete our initial introduction into the ontology management functions available in owlready2. From here we next introduce some of the more advanced features in this API.
To interact with this installment on Jupyter Notebook, we will be using the smaller KKO (Kbpedia Knowledge Ontology), kko.owl
, because it is a bit easier to inspect and manipulate.
General Load Method
Note we are continuing to consolidate our initial load statements into a single routine, which we will often use to begin subsequent installments. We also continue to follow the best practice of using logical names to refer to absolute file addresses.
kko.owl
main = 'C:/1-PythonProjects/kbpedia/sandbox/kko.owl'
# main = 'https://raw.githubusercontent.com/Cognonto/CWPK/master/sandbox/builds/ontologies/kko.owl'
skos_file = 'http://www.w3.org/2004/02/skos/core'
from owlready2 import *
= get_ontology(main).load()
kko
= get_ontology(skos_file).load()
skos kko.imported_ontologies.append(skos)
Having executed these methods with the shift+enter
or Run command from the main menu, we can now do a quick inspection to see if everything has loaded properly. We again use a listing of subclasses of the Products
class:
list(kko.Products.subclasses())
[kko.PrimarySectorProduct,
kko.SecondarySectorProduct,
kko.TertiarySectorService]
Instances
Instance assignments work similarly to classes, except we must relate the new instance to its parent class. In this example, we are adding a camera
instance to our SecondarySectorProduct
class, itself a subclass of Products
. We also add a print
statement to confirm our assignment worked OK:
= kko.SecondarySectorProduct("camera")
camera print(camera.name)
camera
Like for classes, there are multiple methods for creating a new instance. Here is another form:
= kko.SecondarySectorProduct("computer",
computer = kko) namespace
The .instances()
class method can be used to iterate through all Instances of a class (including its subclasses). It returns a generator:
for i in kko.SecondarySectorProduct.instances(): print(i)
kko.camera
kko.computer
Go ahead and substitute ‘Products
‘ for the class name above to verify it also works on subclasses.
As we learned in the last installment, we can also delete the instance and all of its internal references:
destroy_entity(computer)
Data and Object Properties
Recall that the basic statement (assertion) in RDF, the base language of our ontologies, is a ‘triple‘. The triple has the form of subject – property – object (or s-p-o; also, predicate or relation is a synonym for property). Data and object properties may be inferred over in a W3C ontology. Object properties require a defined and named object (instance or class) as its object. Data properties require a datatype as its object, including strings. Annotation properties (see below) also take strings or URIs as their object, but can not be inferred over.
One creates properties in a similar manner to classes. In this example, we are creating the has_color
sub-property of the qualities
property, itself a sub-property of an ObjectProperty
:
with kko:
class has_color(kko.qualities): pass
You will note in this example that we used the underscore character to separate our names to make the property name more readable. Actually, in KKO (and KBpedia) our preferred convention is to use CamelCase with classes initially capitalized, and properties initially lower case. We do not use the underscore. What is important to note here, however, is that these are only best-practice conventions. There is no absolute requirement for classes, individuals or properties to assume a particular naming form.
To see that our new property has been properly added, we can do our standard list method:
list(kko.properties())
We can delete properties and all internal references with the destroy_entity
method. Further, we can make domain and range assignments and other specifications of properties, some addressed below, the others covered in the Additional Documentation section.
Annotations
As noted, annotations are one of the property types where the objects are names or strings or link addresses (IRIs), but over which no reasoning may occur. Annotations provide the labels, definitions, comments, and pointers to the actual objects in the system. We can assign values in a straightforward manner to annotations (in this case, altLabel
):
= ["Mike's computer","PC", "workstation"] computer.altLabel
We can confirm the properties assigned to the computer
instance with the get_properties
method:
kko.computer.get_properties()
{core.altLabel}
We can also see the actual altLabels
were properly assigned:
print(kko.computer.altLabel)
["Mike's computer", 'PC', 'workstation']
You will note that the first label in the example above is shown with double-quotes in order to properly account for the single quote in the label for possession.
Like all properties in the system we can get a listing of the properties and classes that have assigned values for that property with this form of .get_relations
method:
list(skos.altLabel.get_relations())
Indirect Relations
There is a special method in Owlready2 called ‘INDIRECT_
‘. Invoking this brings up results for:
- transitive, symmetric and reflexive properties
- property inheritance (i.e., subproperties)
- classes of an individual
- class inheritance (i.e., parent classes), and
- equivalences (equivalent classes, sameAs individuals).
Here is an example:
print(computer.INDIRECT_altLabel)
["Mike's computer", 'workstation', 'PC']
Property Restrictions
Owlready2 enables us to also place restrictions on our classes through a special type of class constructed by the system.
- some –
Property.some(Range_Class)
- only –
Property.only(Range_Class)
- min –
Property.min(cardinality, Range_Class)
- max –
Property.max(cardinality, Range_Class)
- exactly –
Property.exactly(cardinality, Range_Class)
- value –
Property.value(Range_Individual / Literal value)
- has_self –
Property.has_self(Boolean value)
.
These are the same names and understandings as is used by the Protégé ontology IDE (see CWPK #5). See further Additional Documentation for details.
Operators
Owlready2 provides three logical operators between classes (including class constructs and restrictions):
- ‘&’ – And operator (intersection). For example: Class1 & Class2. It can also be written: And([Class1, Class2])
- ‘|’ – Or operator (union). For example: Class1 | Class2. It can also be written: Or([Class1, Class2])
- Not() – Not operator (negation or complement). For example: Not(Class1).
Save and Exit
When we are finished with our tests, we can File → Save and Checkpoint, Rename our output file, or specify it at the command line (substituting your own local preferences):
file = "C:/1-PythonProjects/kbpedia/sandbox/kko-test.owl", format = "rdfxml") kko.save(
Additional Documentation
Here are links to other owlready2 documentation:
*.ipynb
file. It may take a bit of time for the interactive option to load.