Posted:August 20, 2020

CWPK #19: Exploring the API to OWL

Let’s Get Familiar with Some Basic owlready2 Commands

In our last installment of this Cooking with Python and KBpedia series, we learned some KBpedia terminology and loaded the main KBpedia knowledge graph file, kbpedia_reference_concepts.owl. (Remember, do NOT use the kbpedia_reference_concepts.n3 since owlready2 does not support the Notation3 syntax.) You will need to navigate back to that file location again. One of the aspects of working with Jupyter Notebook is that, once you leave the application, you must re-load your files again whenever you return to the application. As you also recall, it is also necessary to Run the cells in order for a given notebook to restore the states that each cell needs.

In today’s installment we will start to get familiar with some basic commands in owlready2, the API to our OWL2 ontologies. We will then apply these basic approaches to starting efforts to manage these ontologies, which begins with our next installment.

Load and Import the Ontologies

Which environment? The specific load routine you should choose below depends on whether you are using the online MyBinder service (the ‘raw’ version) or local files. See CWPK #17 for further details.

Local File Option

As we instructed in the last installment, the best practice is to provide names to absolute file addresses to make sure you are getting and loading the files you need. Again, in this instance, we call name this file main and we also add some code to verify the file was found by listing its contents:

main = 'C:/1-PythonProjects/kbpedia/sandbox/kbpedia_reference_concepts.owl'
with open(main) as fobj:                           
    for line in fobj:
        print (line)

After you shift+enter to execute the cell contents, or pick Run from the main menu, you will see a rather long file listing. To clear it from the screen, run Cell → All Output → Clear.

The KBpedia full ontology also depends on (‘imports’) two other files: the KBpedia upper ontology, KKO (kko.owl), and the SKOS language that we use for annotations (http://www.w3.org/2004/02/skos/core). The KBpedia full ontology also depends on (‘imports’) two other files: the KBpedia upper ontology, KKO (kko.owl), and the SKOS language that we use for annotations (http://www.w3.org/2004/02/skos/core). As we described in the prior CWPK installment, you will need to download the raw version of kko.owl, and store it in the same location as kbpedia_reference_concepts.owl downloaded in the prior installment. There is no need to download the skos file.

Again, we give names to their absolute file addresses, only this time we do not echo their file listings to screen:

kko_file = r'C:\1-PythonProjects\kbpedia\sandbox\kko.owl' 
skos_file = 'http://www.w3.org/2004/02/skos/core' 

Note one file (kko) is on disk and we use the native Windows file path (with backward slashes) by invoking the ‘r‘ (raw) command switch: r'C:\1-PythonProjects\kbpedia\sandbox\kko.owl'. The other skos file is found off of the Web.

MyBinder Option

If you are running this notebook online, do NOT run the above routines, since the load routines vary somewhat. Please use the following instructions.

main = 'https://raw.githubusercontent.com/Cognonto/CWPK/master/sandbox/builds/ontologies/kbpedia_reference_concepts.owl'

To view this file, run the next cell, otherwise, run the following cells to load all graphs.

import urllib.request 

for line in urllib.request.urlopen(main):
    print(line.decode('utf-8'), end='')
kko_file = 'https://raw.githubusercontent.com/Cognonto/CWPK/master/sandbox/builds/ontologies/kko.owl' 
skos_file = 'http://www.w3.org/2004/02/skos/core' 

Begin the Import

Now that our three files have been given logical names, we are ready to import them into our Jupyter Notebook. Run each of these cells (shift+enter) in sequence:

from owlready2 import *
onto = get_ontology(main).load()

The asterisk (*) after the import statement means that we want to load all modules in the owlready2 package. One of those functions is get_ontology. We have also given our main ontology the name of onto

skos = get_ontology(skos_file).load()
onto.imported_ontologies.append(skos) 
kko = get_ontology(kko_file).load()
onto.imported_ontologies.append(kko) 

We can also place all three commands into a single cell. Note, however, that if you run this consolidated command, that you will see double listings when you invoke print(onto.imported_ontologies) below. In other words, while there is no harm to loading a file again, you are better off only doing the consolidated alone or the three separate loads alone.

You can run the command below to see this behavior. You should then log off or Kernal → Restart & Clear Output and then only load one set before proceeding further.

from owlready2 import *
onto = get_ontology(main).load()

skos = get_ontology(skos_file).load()
onto.imported_ontologies.append(skos) 

kko = get_ontology(kko_file).load()
onto.imported_ontologies.append(kko)

Let’s now test to make sure the ontologies have been loaded OK by checking to see if the base IRIs for all graphs are recognized by the system:

print(onto.base_iri)
http://kbpedia.org/kbpedia/rc#
print(skos.base_iri)
print(kko.base_iri)

We can also confirm that the two additional ontologies have been properly imported:

print(onto.imported_ontologies)

Inspecting Ontology Contents

We can now start checking to see if the components of the ontologies have loaded properly. Let’s first check on the classes:

list(onto.classes())

Now, this listing above is interesting. You will see a few warning messages at the top of the listing. This is due to the fact that a very few KBpedia RCs share the same subClasses, making them essentially equivalent classes. The ones listed here are purposeful and do no harm; generally, however, you want to avoid such duplication.

Next, if you scroll down to the bottom you will see that the listing is actually truncated at the bottom with the [...] indicator. If you were to copy the output listing to an editor you would see there are exactly 1000 items in this list, the default limit for such listings when you first install Jupyter Python. But we know there are more than 58,000 RCs (classes) in the system. To see a complete listing we will need to make a change to our notebook’s configuration file.

Note: This option does not apply to the online MyBinder version.

First, you need to exit this notebook and at your command line create an IPython config file if you don’t already have one:

ipython profile create

Once generated, this config file can be found in your user’s directory (C:\Users\mike.ipython\profile_default\ipython_config.py in my case). Make sure and note the dot in the .ipython directory. Navigate to your appropriate directory and edit this config file to remove the comment for this line and to set the value to ‘0’:

c.PlainTextFormatter.max_seq_length = 0

(which, again, is set to 1000 by default.)

Restart your notebook instance after making this change and run the cells above again. You will now see the full listing of RCs in KBpedia. (A hat tip to StackOverflow for this snippet.)

But, hmmm, where are the classes from the kko and skos imports? All we are showing in this list are the RCs from the default ontology of main.

One of the interesting aspects of owlready2 is its use of what it calls ‘worlds’ to isolate given items into separate namespaces. This allows different projects to be held in memory at one time, including even different open and closed reasoning that may be applied. (A topic for a later installment.)

Now, it is the case that we loaded all three of our ontologies without specifying different ‘world’ namespaces. To see the three combined, let’s actually specify the ‘world’ that is currently active, which is called ‘default’ if not otherwise specified. Rather than our previous onto namespace, let’s now explicitly refer to this default:

list(default_world.classes()) 

Note the full IRI listings for the kko classes at the bottom of the listing. This signals a bit of a namespace recognition problem, that we will address in a few moments.

We can use this same dot approach of namespace.method for other components in our system. (See Additional Documentation below for a listing of such methods available in owlready2.)

In the two examples below we list the annotation properties for both the main (onto) and skos namespaces:

list(onto.annotation_properties())
list(skos.annotation_properties())

Now, one of the RCs we see in our listing is for Eutheria, the technical name for mammals. Using the same format as above we want to get a listing of its subclasses, but adding our rc. prefix in fact does not work:

list(rc.Eutheria.subclasses())

Hmmm, it is not immediately clear why we get the error that ‘rc‘ is not defined.

If we look at the KBpedia Web site we see, in fact, that our prefix to individual RCs is actually http://kbpedia.org/kko/rc/ with the trailing ‘/’. owlready2 documentation indicates it uses the ‘#’ sign as its default separator for vocabulary terms. Since our system uses the ‘/’, perhaps something got screwed up in how owlready2 recognizes our namespace.

One way to deal with this potential problem explicitly is to make a direct assignment for what the IRI prefix should be. We do so via this command, where we are directing the prefix ‘rc‘ to recognize our standard base IRI:

rc = onto.get_namespace('http://kbpedia.org/kko/rc/')

With this new namespace assignment, we run the command again:

list(rc.Eutheria.subclasses())

Voilà! We now have the proper registry of the namespace in our system.

Along with absolute file names that we reference via assigned names, it is also good practice to make sure that our namespaces are properly registered before beginning work with owlready2. (I may discover better tips as we move ahead that I will post when and if discovered.)

We can also check out the properties for this concept:

list(rc.Eutheria.get_class_properties())

And, pull out our definition for the concept:

print(rc.Eutheria.definition)

There is also the alternate IRI sytax for identifying a class, in this case to obtain all of the children, grandchildren, etc., of our Mammal concept (which produces a long list of mammals!):

IRIS['http://kbpedia.org/kko/rc/Mammal'].descendants() 

Since we have used the Python list method quite a bit, we can get direct assistance about the method with the standard command:

help(list)

We can also conduct searches of our RCs, including with wildcards (*) in either the pre or post positions:

onto.search(iri = "*Luggage*")

Another helpful command in owlready2 is to instruct the system what paths to search when it looks for referenced names:

onto_path.append("C:/1-PythonProjects/kbpedia/sandbox")

And, we can get a listing of all such paths registered:

list(onto_path)

Lastly, for this installment, we can close by saving the ontology we have been working on, being careful in this instance to give a different file name to prevent inadvertent overwriting of our initial input file:

onto.save(file = "C:/1-PythonProjects/kbpedia/sandbox/owl-test.owl", format = "rdfxml")

To properly exit the notebook, first pick File → Save and Checkpoint, then File → Close and Halt. This will return you to the main Jupyter files screen, from which you Quit and then close the tab. Return to the command window and finish shutting down the service with ctrl+c. That will return you to the command prompt, from which you may again start up a ‘Jupyter Notebook‘ instance.

Additional Documentation

Here is a listing of owlready2 ontology methods.

NOTE: This article is part of the Cooking with Python and KBpedia series. See the CWPK listing for other articles in the series. KBpedia has its own Web site.
NOTE: This CWPK installment is available both as an online interactive file or as a direct download to use locally. Make sure and pick the correct installment number. For the online interactive option, pick the *.ipynb file. It may take a bit of time for the interactive option to load.
I am at best an amateur with Python. There are likely more efficient methods for coding these steps than what I provide. I encourage you to experiment — which is part of the fun of Python — and to notify me should you make improvements.

Schema.org Markup

headline:
CWPK #19: Exploring the API to OWL

alternativeHeadline:
Let's Get Familiar with Some Basic owlready2 Commands

author:

image:
https://www.mkbergman.com/wp-content/uploads/2020/07/cooking-with-kbpedia-785.png

description:
In today's CWPK installment we will start to get familiar with some basic commands in owlready2, the API to our OWL2 ontologies.

articleBody:
see above

datePublished:

Leave a Reply

Your email address will not be published. Required fields are marked *