A              NATAN –  Environment for creation and management of OWL ontologies

A.1          Basic Information

Maintaining ontologies involves performing some generic repetitive tasks, which requires taking semantic consistency into account. One of the possible sources of problems comes from the fact that the concepts are usually related to several other concepts. In addition, there are often some semantic dependencies between concepts or relationships. This means that the creation of new concepts can be tedious and difficult because it is repetitive and all of the semantic dependencies have to be met.

NATAN is a tool for creating and manipulating ontologies in a scripting environment (i.e. Python). The tool enables the possibility to join the many useful libraries and features of the scripting environment, while being able to access and manipulate ontologies.

A.1.1      Basic Terms

The method of the tool is based on following principles:

·        Mapping between object-oriented environment and ontologies is defined. It is based on accessing the conceptual and property axioms through object interface, which is similar to Smalltalk's object model. The system is backed-up by an OWL reasoner, which is used to store the knowledge base and infer the new facts upon query.

·        Manipulation of the ontologies is performed based on calling the appropriate methods of the object model, which in turn call the reasoner to resolve the queries and reflect the changes in the knowledge base.

·        The object model can be seen as a wrapper for concepts and relations, which follows the set-theoretic semantics of the description logic version of the OWL.

The current implementation technologies include:

·        Jena and Pellet OWL reasoner

·        OWL-DL version of the OWL language

·        RDQL and simple triple like queries from the Jena model.

A.1.2      Method Description

The deep integration of scripting languages and Semantic Web has introduced an idea of importing the ontologies directly into the programming context so that its classes are usable alongside classes defined normally. Such integration encourages separation of concerns among declarative and procedural and encourages a new wave of programming, where problems can be defined by using description logics and manipulated by powerful dynamic scripting languages.

Intensional sets as introduced in are sets that are described with OWL DL's construct and according to this description, encompass all fitting instances. A sample intensional set can be defined by using Notation3 (N3) language as:

Person a owl:Class; rdfs:subClassOf :Mortal,

It simply states that Person is also a Mortal. Assuming we introduce two instances :

John a :Person and :Jane a :Mortal,

The instances of a class Person are both John and Jane.

Terminology-wise, a metaclass is simply "the class of a class". Any class, whose instances are themselves classes, is a metaclass. A metaclass-based implementation of the above is based on the core metaclass Thing, whose constructor accepts two main attributes, i.e. default namespace and N3 description of the set (it is also possible to use NTriples or RDF/XML).  The instance of the Thing metaclass is then a python class, which represents the OWL Class having the same name. Following the above example class Person can then be created with a python construct:

Person = Thing('Person', (baseClass),

           {defined_by: 'a owl:Class; rdfs:subClassOf :Mortal',\

            namespace: 'http://samplens.org/test#'})

This creates a python class Person with two main attributes and a base class from which it can inherits the needed methods. It also updates the knowledge base with the new concept. The individual John can then be instantiated simply by calling  

John = Person().

This statement calls the default constructor of the class Person, which provides support for asserting a new OWL individual into the knowledge base. A similar metaclass is used for the OWL Property except that it can not be instantiated. The constructor is used here for different purposes, i.e. to create a relation between classes or individuals. The notion of importing the ontology into the python's namespace is then a matter of decomposing the ontology into the groups of intensional sets, generating python classes for these sets and enacting the instances.  A similar approach can be taken to create a serialization of the created ontology by processing all the existing N3 descriptions and instances and parse their descriptions into a file.

The metaclass-based implementation of intensional sets is not bound to the python language and can be easily implemented in any metaclass-based scripting language. The metaclass programming can provide a transparent way how to generate new OWL Classes and Properties and provide support for the necessary altering of the nature of the python classes. Since metaclasses act like regular classes it possible to extend their functionality by inheriting from the base metaclass. It is also simple to automate complex tasks needed for accessing the knowledge base, reasoner and processing the mapping between OWL-DL's concepts and their respective python counterparts.

A.1.3      Scenarios of Use

A sample session shows an in-line declaration of a class Person. This is implemented by calling a static method new of the metaclass Thing (the static method new} is used to hide the complex call introduced in the previous section. An instance is created by calling the Person's constructor, which in fact creates an in-line declaration of the OWL individual (John}). The print statements show the Python's view of the respective objects, i.e. Person as a class and John as an instance of the class Person. We also show a more complex definition of the PersonWithSingleSon, which we will later use to demonstrate the reasoning about property assertions. 

>>> from Thing import Thing

>>> Person = Thing.new('Person a owl:Class .')

>>> John = Person('John')

>>> print Person

<class 'Thing.Person'>

>>> print John

<Thing.Person object at 0xb7d0b50c>

>>> PersonWithSingleSon = Thing.new("""PersonWithSingleSon \

      a  owl:Class ; rdfs:subClassOf   [ a  owl:Restriction ;

     owl:cardinality "1"^^<http://www.w3.org/2001/XMLSchema#int> ;

     owl:onProperty :hasSon

                                         ] ;

     rdfs:subClassOf  [ a  owl:Restriction ;

     owl:cardinality "1"^^<http://www.w3.org/2001/XMLSchema#int> ;

     owl:onProperty :hasChild ] .""")

 

A similar way can be used for in-line declarations of OWL properties. Compared to a class declaration the returned Python class can not be instantiated (i.e. returns None}). 

>>> from PropertyThing import Property

>>> hasChild = Property.new('hasChild a owl:ObjectProperty .')

>>> print hasChild

<class 'PropertyThing.hasChild'>

>>> hasSon = Property.new('hasSon a owl:ObjectProperty ;

                           rdfs:subPropertyOf :hasChild .')

Properties are naturally used to assign relationships between OWL classes or individuals, which can be as simple as calling:

>>> Bob = PersonWithSingleSon('Bob')

>>> hasChild(Bob, John)

 

Assuming we have declared several instances of the class Person we can find them by iterating over the class list.

It is also possible to ask any triple like queries (the query shown also demonstrates reasoning about the property assertions).

>>> for individual in Person.findInstances():

...     print individual, individual.name

<Thing.Man object at 0xb7d0b64c> Peter

<Thing.Person object at 0xb7d0b50c> John

<Thing.Person object at 0xb7d0b6ec> Jane

 

>>> for who in hasSon.query(Bob):

...     who.name

'John'

>>> print hasSon.query(Bob, John)

1

 

A.1.4      External Links and Publications

1. Vrandecic, D., Deep Integration of Scripting Languages and Semantic Web Technologies, In Sren Auer, Chris Bizer, Libby Miller, 1st International Workshop on Scripting for the Semantic Web SFSW 2005 , volume 135 of CEUR Workshop Proceedings. CEUR-WS.org, Herakleion, Greece, May 2005. ISSN: 1613-0073

2. Pellet OWL Reasoner, see http://www.mindswap.org/2003/pellet/index.shtml

3. RacerPro Reasoner, see http://www.racer-systems.com

4. Jena A Semantic Web Framework for Java, see http://www.hpl.hp.com/semweb/ jena2.htm.

5. G. van Rossum, Computer programming for everybody. Technical report, Corpora-

tion for National Research Initiatives, 1999

6. Baader, F., Calvanese, D., McGuinness, D.,L., Nardi, D. and Patel-Schneider,P., F.

editors. The description logic handbook: theory, implementation, and applications. Cambridge University Press, New York, NY , USA, 2003.

A.2          Integration Manual

A.2.1      Dependencies

The current version of NATAN API was written to demonstrate the ideas of the deep integration between Python and OWL. It has been tested under Linux, however it should work under windows.

 

If you have any question or problems with the package, please

e-mail to:  seth-users@projects.semwebcentral.org

 

NATAN requires Java Runtime Environment version 1.4 and two libraries:

- pellet-1.3-beta2 http://www.mindswap.org/2003/pellet/

- JPype 0.5.2.1 http://jpype.sourceforge.net/

Note on JPype installation:

If you're running Linux and default JPype configuration doesn't work for you, you might need to have a look at the jpype file:/(path_to_python)/python2.4/site-packages/jpype/_linux.py and edit the function getDefaultJVMPath()  to return the correct path to JVM

A.2.2      Installation

Installation of NATAN follows a standard Python package installation, i.e.

cd seth

python setup.py install

A.2.3      Configuration

The configuration file for the NATAN can be found in file seth/config.py. Several variables can be defined:

KB_LIB_PATH – sets the path to the reasoner libraries (Pellet, Sesame)

OWL_NS – sets the namespace of the OWL to be used

RDF_NS – sets the namespace of the RDF/RDFS to be used

KB_URL – sets the URL of the reasoner


A.3          Development Manual

A.3.1      Tool Structure

NATAN is developed as a standard Python package with several modules, each in its own file. The following schema gives an overview of the base classes and shows the meta-class based facility that NATAN uses to generate the classes and methods for the corresponding OWL concepts and roles.

The actual structure of the package is following:

Module Hierarchy

Class Hierarchy

A.3.2      Method Implementation

Type DefsGenerator

object --+    
         |    
    Parser --+
             |
            DefsGenerator

 


Definitions Generator parses the RDF/XML files and yields set of class, property definitions and their instances. It is based on the rdflib package.


Method Summary

 

getClassDefs(self)

 

getClassInstances(self)

 

getDatatypePropertyDefs(self)

 

getDatatypePropertyInstances(self)

 

getFunctionalPropertyDefs(self)

 

getFunctionalPropertyInstances(self)

 

getObjectPropertyDefs(self)

 

getObjectPropertyInstances(self)

Inherited from Parser: __init__, check, getDefaultNamespace, getImports, getNamespaces, resolve, retrieve, serialize
Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Type DParser

object --+    
         |    
    Parser --+
             |
            DParser

 


DParser parses the definition and extracts class/property URIs, which are then used to create the Python class name.


Method Summary

 

__init__(self)

 

getClassMap(self, definition)
Get the (URI, pyClassName) tuple from the given owl:Class definition.

 

getPropertyMap(self, definition)
Get the (URI, pyClassName) tuple from the given owl:Property definition.

Inherited from Parser: check, getDefaultNamespace, getImports, getNamespaces, resolve, retrieve, serialize
Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__



Class Variable Summary

Namespace

OWL = rdflib.URIRef('http://www.w3.org/2002/07/owl#')

Namespace

RDFS = rdflib.URIRef('http://www.w3.org/1999/02/22-rdf-s...

Inherited from Parser: all, store

Type JStore

object --+    
         |    
 Singleton --+
             |
            JStore

 


JStore provides access to the java-based knowledge base and reasoner (i.e. Jena, Pellet). It uses JPype to call Java methods. JStore aim is mainly to hide JPype configuration and its complex calls. JStore is an initial version of the more complex Knowledge Base Interface, which should provide support for other OWL/RDF knowledge bases and reasoners (e.g. Racer, KAON2, etc.). Unlike rdflib Store it should support OWL-DL inferences through reasoner.


Method Summary

 

__init__(self)
Setup JPype classpath, initialize JVM, Jena's OntModel and Pellet

 

__del__(self)

 

addN3(self, definition, base)

 

addNTriples(self, definition)

 

addRDFXML(self, definition)

 

classify(self)
Wrapper for the Pellet's classify method.

 

contains(self, sub, prop, ind)
Wrapper for the Jena contains method.

 

createInferenceModel(self)
Wrapper for the Jena createInferenceModel.

 

instancesOf(self, uri)
Wrapper for the Pellet's getInstances.

 

listObjectsOfProperty(self, ind, prop)
Wrapper for the Jena's listObjectOfProperty method.

 

read(self, file, format)

 

toStringHelper(self, definition, format, ontModel)
Helper method to get pretty-N3 of the definition.

 

write(self, format)

Inherited from Singleton: getInstance
Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Module seth.Meta

Classes

owlNothing

Class representing the OWL:Nothing concept

owlThing

Class representing the OWL:Thing concept

Property

Property is a metaclass for creating Python objects from OWL Properties.

Thing

Thing is a metaclasses for creating Python classes/instances from OWL-DL definitions of OWL classes/individuals.

Type Property

object --+    
         |    
      type --+
             |
            Property

 


Property is a metaclass for creating Python objects from OWL Properties. Behaves exactly the same as Thing, but generated classes can not be instantiated (None).


Method Summary

 

__init__(cls, name, bases, dct)

 

__call__(cls, *lstArgs, **dictArgs)

 

new(defined_by)
(Static method)

 

q(cls, arg1, arg2)

 

setOntModel(ontModel)
(Static method)

 

toN3(cls)

Inherited from type: __cmp__, __delattr__, __getattribute__, __hash__, __new__, __repr__, __setattr__, __subclasses__, mro
Inherited from object: __reduce__, __reduce_ex__, __str__



Class Variable Summary

NoneType

ontModel = None                                                                  

Inherited from type: __bases__, __basicsize__, __dictoffset__, __flags__, __itemsize__, __mro__, __name__, __weakrefoffset__

Type Thing

object --+    
         |    
      type --+
             |
            Thing

 


Thing is a metaclasses for creating Python classes/instances from OWL-DL definitions of OWL classes/individuals. It parses the class/individual definition, adds this definition to the JStore and returns a Python's class/instance.


Method Summary

 

__init__(cls, name, bases, dct)
Metaclass constructor, which creates the python class cls; it also adds the owl definition to the model and registers the URI, cls mapping.

 

__call__(cls, *lstArgs, **dictArgs)
Constructor of the python class cls, called when instantiating the class.

 

instances(cls)
Called to get instances of the class cls.

 

new(definedBy)
Static method to wrap the complex metaclass call, which creates python classes. (Static method)

 

setOntModel(ontModel)
(Static method)

 

toN3(cls)

Inherited from type: __cmp__, __delattr__, __getattribute__, __hash__, __new__, __repr__, __setattr__, __subclasses__, mro
Inherited from object: __reduce__, __reduce_ex__, __str__



Class Variable Summary

NoneType

ontModel = None                                                                  

Inherited from type: __bases__, __basicsize__, __dictoffset__, __flags__, __itemsize__, __mro__, __name__, __weakrefoffset__

Class ModelFactory


Generate OntModel from the given ontology (File). Parses the file, calls the metaclasses to generate python classes from OWL constructs and registers each python class/instance as an attribute of the OntModel instance. OntModel instance is then registered in the sys.modules, which enables the import of the generated python classes/instances.


Method Summary

 

__init__(self, store, ontology)

 

countRawTriples(self)

 

createClass(self, classAxiom)
Create python class from owl:Class.

 

createInstance(self, owlCls, instURI)
Create python class instance from owl:Individual.

 

createModel(self)
Create python OntModel from owl:Ontology.

 

createOntModel(mod, url)
Static helper function. (Static method)

 

createProperty(self, propertyAxiom)
Create python property from owl:Property.

Type OntModel

object --+
         |
        OntModel

 


Ontology interfaces which will store all the Python classes/objects, namespaces and mappings for the given OWL:ontology.


Method Summary

 

addImport(self, ontology)

 

addNSMapping(self, pyClass, ontClass)

 

bind(self, name, namespace)
Bind prefix to namespace.

 

generateHeader(self)
Generates N3 header.

 

getNS(self)
Generator over (prefix, namespace) tuples.

 

getOntClass(self, pyClass)
Get the URI of the python object.

 

getPyClass(self, ontClass)
Get python object representing the given URI

Inherited from object: __init__, __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Type Parser

object --+
         |
        Parser

 

Known Subclasses:

DefsGenerator, DParser


Common methods for the parsers (DefGenerator, DefParser), used mainly to parse and manage the class/property definitions.


Method Summary

 

__init__(self, store, format)

 

check(self)
Helper method for debuging purposes.

 

getDefaultNamespace(self)
Get the default namespace for the ontology (obsolete).

 

getImports(self, subject)
Get the ontology imports.

 

getNamespaces(self)
Generator over the ontology's namespaces.

 

resolve(self, id, container)
Resolves the blank nodes for the given id.

 

retrieve(self, identifier)
Extract triples based on the given identifier.

 

serialize(self, c)
Serialize the set of triples into a definition in a given format.

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__



Class Variable Summary

list

all = []

Namespace

OWL = rdflib.URIRef('http://www.w3.org/2002/07/owl#')

Namespace

RDFS = rdflib.URIRef('http://www.w3.org/1999/02/22-rdf-s...

NoneType

store = None                                                                  

Type Singleton

object --+
         |
        Singleton

 

Known Subclasses:

JStore


Method Summary

 

getInstance(cls, *lstArgs)
Call this to instantiate an instance or retrieve the existing instance. (Class method)

Inherited from object: __init__, __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__



Class Variable Summary

type

__metaclass__ = seth.SingletonMixin.MetaSingleton

Type MetaSingleton

object --+    
         |    
      type --+
             |
            MetaSingleton

 


Method Summary

 

__call__(cls, *lstArgs, **dictArgs)

 

__new__(metaclass, strName, tupBases, dict)
(Static method)

Inherited from type: __cmp__, __delattr__, __getattribute__, __hash__, __repr__, __setattr__, __subclasses__, mro
Inherited from object: __init__, __reduce__, __reduce_ex__, __str__



Class Variable Summary

Inherited from type: __bases__, __basicsize__, __dictoffset__, __flags__, __itemsize__, __mro__, __name__, __weakrefoffset__

 

A.4          Manual for Adaptation to Other Domains

NATAN is a general API for the creation and manipulation with ontologies. No further enhancements are necessary to adopt it in other domains

A.4.1      Configuring to Other Domain

The configuration file for the NATAN can be found in file seth/config.py. Several variables can be defined:

KB_LIB_PATH – sets the path to the reasoner libraries (Pellet, Sesame)

OWL_NS – sets the namespace of the OWL to be used

RDF_NS – sets the namespace of the RDF/RDFS to be used

KB_URL – sets the URL of the reasoner


A.4.2      Dependencies

NATAN requires Java Runtime Environment version 1.4 and two libraries:

- pellet-1.3-beta2 http://www.mindswap.org/2003/pellet/

- JPype 0.5.2.1 http://jpype.sourceforge.net/