Catch-22 on Imported Classes?

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Catch-22 on Imported Classes?

Mike Bergman
Hi Jean-Baptiste,

owlready2 is fantastic stuff (even though there are still some rough edges. ;) ). Thanks!

I am importing large sets of CSV files of classes that define the structural (subClassOf) relationships in my ontology. I begin with a small ontology stub, and then import from there. The input CSV files are simple s-p-o text files, not in any particular order. Each class in the input files also has a line devoted to it assigning to owl:Thing.

The input routine has two passes. The first loop defines the new class to the stub ontology (via Thing) per the documentation:

id = types.new_class(id_frag, (Thing,))

The second pass then assigns the actual parent class to the new class. (NB: this loop was pretty hard to debug because variable types needed to be either strings or classes, depending):

id.is_a.append(parent)

Both of these loops are now working fine. However, the import file reflects a nice hierarchical structure, with NONE of the new classes a direct child of owl:Thing. (Thing is initially required per the documentation to register the classes in the first place.) The starting stub ontology has the actual tie-in points for the upper new classes; all imported new classes are ultimately descendants of owl:Thing. I want to remove the superfluous owl:Thing assignments now that the new classes have been imported successfully.

To do so, in an interactive environment, this statement works fine:

id.is_a.remove(owl.Thing) or id.is_a.remove(var)

But, when embedded in the loop, this statement always fails. I have tried all sorts of combinations of commands and named or prefixed classes. One trick is to make sure my variable references are typed as classes using a tip discussed in these lists:

id = getattr(rc, parent)

But, if parent is so classed in the routine it seems to fail. (That was also the case when trying to use a second superclass in the tuple with Thing in the first loop.)

My suspicion is that Thing is universally global (even more than World) and is not reachable with this standard call.

Any ideas about how to use these methods correctly or workarounds?

Thanks for your tool and your time,

Mike

Reply | Threaded
Open this post in threaded view
|

Re: Catch-22 on Imported Classes?

Mike Bergman
Hi All,

Sorry to clog the list; I have figured out this 'Catch-22' issue I first posted. I withdraw my request for help.

As a total Python newbie, I first had to struggle with the questions of Python scope called LEGB. That was only a minor cause of the problems here. What I discovered were mismatches I was making in the interplay of base ontology, imported ontologies, namespaces, and internal 'Worlds' in owlready2.

Here, in brief, is what I learned. I'm sure my points are not fully correct, so I encourage anyone to add to or modify this list:

First, when loading an ontology, I give it a 'world' namespace assigned to the 'World' internal global namespace for owlready2. Since I am only doing bespoke development in Python at a given time, I can afford to claim the entire space and perhaps lessen other naming problems. Maybe this is superfluous, but I have found it to be a recipe that works for me.

Second, I needed to make sure that internal version IRIs among the working and imported ontologies were consistent. Since I'm versioning my ontologies, I had a mismatched declaration.

Third, when one imports an ontology into the working ontology (declaring the working ontology being step one), all ontologies available to the import are available to the working ontology. However, if one wants to modify or add items to these imported ontologies as opposed to simply calling them (as was my use case of wanting to delete the temporary owl:Thing placeholder when importing a new class), each one needs to be explicitly declared.

Fourth, it appears essential to declare the namespaces for these imports under the current working ontology. Thus, here are the example declarations that ended up working for me:


kb = world.get_ontology(kbpedia).load()
rc = kb.get_namespace('http://kbpedia.org/kko/rc/')              

skos = world.get_ontology(skos_file).load()
kb.imported_ontologies.append(skos)
core = world.get_namespace('http://www.w3.org/2004/02/skos/core#')

kko = world.get_ontology(kko_file).load()
kb.imported_ontologies.append(kko)
kko = kb.get_namespace('http://kbpedia.org/ontologies/kko#')


Last, once declared, it also appears essential to be cognizant that these separate namespaces need to be addressed explicitly in the code. One challenge is to make sure that variables passed in loops get the proper Python class type when doing class operations such as the following:


 var1 = getattr(rc, id_frag)
 var1.is_a.remove(owl.Thing)


The above needs to be repeated if there are more than one namespaces beyond 'rc'.

More than one namespace in the working ontology does complicate matters quite a bit, but that is also the more realistic architecture and design approach, at least for my own work.

I welcome corrections or expansions of these guidelines!

Thanks!

Best, Mike

Reply | Threaded
Open this post in threaded view
|

Re: Catch-22 on Imported Classes?

Jiba
Administrator
Hi,

I think you guessed it right. The difficulty is that, contrary to Python module, and ontology X may define entities in a namespace Y, for example the ontology http://test.org/X.owl may define the class http://test.org/Y.owl/Class. This requires more complex structure/syntax to achieve in Python.

Jiba