Resource Description Framework (RDF)


What's this all about

RDF describes any object as a collection of triples, each consisting of a subject, a predicate and an object. The predicate (also called a property) denotes the relationship. More details (definition, syntax, tutorials) are available at W3C site and elsewhere online.

RDF is a data model, not format

The data model consists of objects and their relationships. Objects are modeled in RDF as Classes (rdf:Class), and Classes have specific Instances.  Relationships are modeled with Properties (rdf:Property). 

Formats (serialization)

Once a data model is defined, it could be serialized into different formats, like:




OWL Web Ontology Language

OWL is built on top of RDF, and while it imposes restrictions on what is allowed to represent, compared to RDF, this is for a good reason. OWL, and especially its subsets OWL-Lite and OWL-DL allows automatic machine reasoning. 

In OWL, there are Object properties and Data properties (owl:Property, which is a subclass of  rdf:Property). An Object property specifies a relation between Instances, while a Data property specifies a relation between an Instance and a simple data value (string, integer, etc.).  Properties can not be used as Classes and vice versa.

Rules of Thumb for OWL DL Ontologies

The OpenTox resources data model


This allows easily to create statements like "A Model is created by an Algorithm". Below is an example of the property "algorithm" (or should it be better "isCreatedByAlgorithm"?). It is a subclass of owl:FunctionalProperty, which means a Model can be linked to only one Algorithm via this property.

    <owl:FunctionalProperty rdf:ID="algorithm">
        <rdf:type rdf:resource="&owl;ObjectProperty"/>
        <rdfs:domain rdf:resource="#Model"/>
        <rdfs:comment rdf:datatype="&xsd;string"
            >The algorithm, used to create the Model</rdfs:comment>
        <rdfs:isDefinedBy rdf:datatype="&xsd;string"
        <rdfs:range rdf:resource="#Algorithm"/>
        <rdfs:subPropertyOf rdf:resource="#model"/>

Properties are defined by their domains (rdfs:domain) and ranges (rdfs:range). In this case, the domain is Model and the range is Algorithm.


The Model and Algorithm classes are defined as owl:Class and are subclass of the class OpentoxResource (all OpenTox objects in opentox.owl are defined as descendants of OpentoxResource). 

<?xml version="1.0"?>

    <!ENTITY owl "" >
    <!ENTITY swrl "" >
    <!ENTITY dc "" >
    <!ENTITY swrlb "" >
    <!ENTITY xsd "" >
    <!ENTITY rdfs "" >
    <!ENTITY rdf "" >
    <!ENTITY protege "" >
    <!ENTITY xsp "" >

<rdf:RDF xmlns=""
    <owl:Ontology rdf:about="">
        <dc:contributor rdf:datatype="&xsd;string"></dc:contributor>
        <dc:creator rdf:datatype="&xsd;string">OpenTox</dc:creator>
        <dc:date rdf:datatype="&xsd;string">2009-11-22</dc:date>
        <dc:identifier rdf:datatype="&xsd;string"
        <dc:title rdf:datatype="&xsd;string">OpenTox API</dc:title>
        <rdfs:comment rdf:datatype="&xsd;string">OpenTox resource ontology</rdfs:comment>
        <owl:imports rdf:resource=""/>
    <owl:Class rdf:ID="Model">
        <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
        <dc:creator rdf:datatype="&xsd;string"
            >The model creator (perhaps a link to User resource)</dc:creator>
        <dc:date rdf:datatype="&xsd;string"
            >The date of model creation</dc:date>
        <dc:format rdf:datatype="&xsd;string"
            >The native format of the model content (e.g. PMML, Weka model, etc.)</dc:format>
        <dc:identifier rdf:datatype="&xsd;string"
        <dc:rights rdf:datatype="&xsd;string"></dc:rights>
        <dc:title rdf:datatype="&xsd;string"></dc:title>
    <owl:Class rdf:ID="Algorithm">
        <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
        <dc:description rdf:datatype="&xsd;string"></dc:description>
        <dc:identifier rdf:datatype="&xsd;string"
        <dc:publisher rdf:datatype="&xsd;string"></dc:publisher>
        <dc:source rdf:datatype="&xsd;string">Reference</dc:source>
        <dc:title rdf:datatype="&xsd;string">Name of the algorithm</dc:title>
        <owl:versionInfo rdf:datatype="&xsd;string">1.1</owl:versionInfo>
        <rdfs:comment rdf:datatype="&xsd;string"
            >Provides access to OpenTox algorithms</rdfs:comment>
        <rdfs:seeAlso rdf:datatype="&xsd;string"

Vocabularity from other ontologies can be used via name spaces, e.g. dc:identifier is a property, defined in Dublin Core



What if the relationship is not a binary one?

An attempt to describe in RDF the statement below is less trivial:

the LogP value of compound_2 is -2.20

At first sight the statement below is sufficient to describe , provided that XlogP is defined in the Blue Obelisk Algorithms ontology.

#N3 notation
<compound_2> blueobelisk:XlogP -2.20 .

However, this is not correct in OWL, since XlogP is defined as an instance of owl:Class in the BlueObelisk ontology, while the above statement attempts to use it as a predicate (rdf:Property). This is a clear case where higher order relationships are involved, and fortunately, there is a W3C document, telling how these could be handled Defining N-ary Relations on the Semantic Web.

To summarize, one needs to introduce intermediate classes, encapsulating each of the binary relationships, and to define again relationship between the resulting classes.


In our case, the statement could be represented as several binary relationships:

  1. IntermediateClass: [LogP value -2.20]
  2. The original statement: [compound_2 hasValue IntermediateClass1]


The first relationship requires defining a new class for description of LogP, which is a Feature, in terminology of OpenTox objects. We might select to use directly BlueObelisk class, but this will make harder to integrate other features, which are not from Blue Obelisk ontology. The Feature class is related to several other classes in the OpenTox API.

Feature class:

#Definition of Feature class in N3 format
ot:Feature a owl:Class .

ot:Feature owl:disjointWith ot:Compound , ot:Model ;
	owl:versionInfo "1.1"^^xsd:string ;
	dc:source ""^^xsd:string ;
	rdfs:subClassOf ot:OpentoxResource ;
	dc:identifier "/feature/{featureid}"^^xsd:string ;
	dc:title ""^^xsd:string ;
	dc:description ""^^xsd:string .

#Feature may originate from a Dataset, or generated by Model or ALgorithm
ot:hasSource a owl:ObjectProperty ;
	rdfs:domain ot:Feature ;
	a owl:FunctionalProperty ;
	rdfs:range _:node14kimc0fpx9 .

_:node14kimc0fpx9 a owl:Class ;
	owl:unionOf _:node14kimc0fpx10 .

_:node14kimc0fpx10 rdf:first ot:Model ;
	rdf:rest _:node14kimc0fpx11 .

_:node14kimc0fpx11 rdf:first ot:Algorithm ;
	rdf:rest _:node14kimc0fpx12 .

_:node14kimc0fpx12 rdf:first ot:Dataset ;
	rdf:rest rdf:nil .

ot:units a owl:DatatypeProperty ;
	dc:title "Units"^^xsd:string ;
	rdfs:comment "Units for a feature value"^^xsd:string ;
	owl:versionInfo "TODO: make use of units ontology"^^xsd:string .

•and FeatureValue class:

ot:FeatureValue a owl:Class .

#FeatureValue class
ot:FeatureValue rdfs:comment "Encapsulates Feature and simple values"^^xsd:string ;
	dc:identifier ""^^xsd:string ;
	rdfs:subClassOf ot:OpentoxResource .

#FeatureValue has 'value' predicate, allowing to assign values of simple types
ot:value a owl:FunctionalProperty , owl:DatatypeProperty ;
	rdfs:comment "Literal"^^xsd:string ;
	rdfs:domain ot:FeatureValue ;
	dc:title "Feature value"^^xsd:string .

#FeatureValue has 'feature' predicate, allowing to specify the Feature in question. 
#Only one feature is allowed.
ot:feature a owl:FunctionalProperty ;
	rdfs:range ot:Feature ;
	rdfs:comment "FeatureValue contains a value for specific Feature, specified by this relationship."^^xsd:string ;
	rdfs:domain ot:FeatureValue ;
	a owl:ObjectProperty ;
	rdfs:isDefinedBy ""^^xsd:string .

Now we are ready to create RDF statement "Compound hasValue FeatureValue".  However, in order to specify this association belongs only to a certain dataset, we need additional classes and relationships.  Recall in RDF everything is described in triples, and there is no way to use constructs like <Dataset>all the entries listed inside</Dataset>as in XML. Relationships as memberships needs to be specified explicitly.

The next challenge is to describe in RDF the following statement:

"In dataset_1, the LogP value of compound_2 is -2.20 and measured value of endpoint_3 is 'Active'"


In order to define Dataset membership, we introduce class DataEntry, which consists of single Compound and multiple FeatureValues.
ot:DataEntry a owl:Class .

#DataEntry class
ot:DataEntry dc:identifier "/dataset/{datasetid}/compound/{compoundid}?feature_uri[]=featureuris"^^xsd:string ;
	dc:title ""^^xsd:string ;
	owl:versionInfo "1.1"^^xsd:string ;
	rdfs:comment "Encapsulates a dataset entry - defined by a single Compound (or conformer) and multiple FeatureValues. Could be regarded as \"Compound with features\""^^xsd:string 
#A predicate, defining set of feature values in DataEntry
ot:values a owl:ObjectProperty ;
	rdfs:range ot:FeatureValue ;
	rdfs:comment "A DataEntry is defined with a single compound and multiple feature values. This property sets the relationship between a DataEntry and multiple FeatureValues"^^xsd:string ;
	rdfs:isDefinedBy ""^^xsd:string ;
	rdfs:domain ot:DataEntry .

#A predicate, defining the Compound in the DataEntry
ot:compound a owl:FunctionalProperty ;
	rdfs:isDefinedBy ""^^xsd:string ;
	rdfs:range ot:Compound ;
	rdfs:domain ot:DataEntry ;
	a owl:ObjectProperty ;
	rdfs:comment "A DataEntry is defined with a single compound and multiple feature values. This property sets the relationship between a DataEntry and a Compound"^^xsd:string .

#dataEntry property, which relates Dataset with DataEntries
ot:dataEntry a owl:ObjectProperty ;
	rdfs:isDefinedBy ""^^xsd:string ;
	rdfs:range ot:DataEntry ;
	rdfs:domain ot:Dataset ;
	rdfs:comment "A Dataset contains multiple DataEntries.  This property specifies the relationship between Dataset and DataEntry."^^xsd:string .

•Finally, the Dataset representation in N3 format:

      a       ot:Dataset ;
      dc:identifier "http://myservice/dataset/{datasetid}"^^xsd:string ;
      dc:source ""^^xsd:string ;
      dc:title "CPDBAS"^^xsd:string ;
              [ a       ot:DataEntry ;
                ot:compound default:benzene ;
                        [ a       ot:FeatureValue ;
                          ot:feature default:MultiCellCall ;
                          ot:value "true"^^xsd:boolean
                        ] ;
                        [ a       ot:FeatureValue ;
                          ot:feature default:XLogPDescriptor ;
                          ot:value "-2.02"^^xsd:float
              ] .

Compounds and Features might be defined in the same RDF document (below), or referenced with URI as external resources.

#The compound
      a       ot:Compound ;
      dc:identifier "http://myservice/compound/{compoundid1}"^^xsd:string ;
#this is optional
      ot:conformer default:Conformer_1 .

#Feature - XLogP
      a       ot:Feature ;
      dc:identifier "http://myservice/feature/{featureid2}"^^xsd:string ;
      dc:title "XLogP"^^xsd:string ;

#This feature has been generated by XLogPCalculation algorithm
      ot:hasSource default:XLogPCalculation ;

#Reference to endpoint ontology
      ot:isA  dc:OctanolWaterPartitioningCoefficient_Kow .

#Algorithm for XLogP calculation
      a       ot:Algorithm ;
      dc:identifier "http://myservice/algorithm/{algorithmid}"^^xsd:string ;
      dc:title "XLogP"^^xsd:string ;
#sameAs BlueObelisk XLogP algorithm
      =       <> .

OpenTox API ontology

All OpenTox classes and properties are defined in openTox.owl . This ontology is expected to be available at The namespace prefix used in all examples is "ot:". Example instances of all OpenTox objects are available here.

How this is related to OpenTox REST services

OpenTox classes and properties are defined to follow closely the objects, defined in API 1.1. Some additional objects are introduced, in order to model relationships other than binary ones, as recommended by W3C. These (e.g. DataEntry, FeatureValue) are used for RDF representations of the main objects and not necessarily appear as REST resources.


OpenTox services work with RDF representations of instances of OpenTox classes. For example an Algorithm service would return the following representation of an Algorithm
   <ot:Algorithm rdf:ID="AlgorithmSVM">
        <dc:contributor rdf:datatype="&xsd;string"
        <dc:creator rdf:datatype="&xsd;string"
        <dc:date rdf:datatype="&xsd;string">2009-11-18</dc:date>
        <dc:description rdf:datatype="&xsd;string"
            >Training Algorithm for Support VectorMachine Regression Models</dc:description>
        <dc:format rdf:datatype="&xsd;string">text/xml</dc:format>
        <dc:identifier rdf:datatype="&xsd;string"
        <dc:publisher rdf:datatype="&xsd;string"
        <dc:relation rdf:datatype="&xsd;string"
        <dc:rights rdf:datatype="&xsd;string"
        <dc:source rdf:datatype="&xsd;string"
        <dc:title rdf:datatype="&xsd;string"
            >Support Vector Machine Regression</dc:title>
        <ot:parameters rdf:resource="#SVMParam1"/>
        <ot:parameters rdf:resource="#SVMParam2"/>
        <ot:parameters rdf:resource="#SVMParam3"/>
        <ot:parameters rdf:resource="#SVMParam4"/>
        <ot:parameters rdf:resource="#SVMParam5"/>
        <ot:parameters rdf:resource="#SVMParam6"/>
        <ot:parameters rdf:resource="#SVMParam7"/>
        <ot:parameters rdf:resource="#SVMParam8"/>
        <ot:statisticsSupported rdf:datatype="&xsd;string"
        <ot:statisticsSupported rdf:datatype="&xsd;string"
        <ot:statisticsSupported rdf:datatype="&xsd;string"
        <ot:statisticsSupported rdf:datatype="&xsd;string"
        <owl:sameAs rdf:resource=""/>
        <ot:isA rdf:resource=""/>

More examples are available at subtopics of this page and in opentox-examples.owl

Linking with other ontologies

In the example below, the SVM algorithm is defined to be related to RegressionEagerSingleTarget instance, defined in Algorithm Types ontology.

<ot:Algorithm rdf:ID="AlgorithmSVM">
    <ot:isA rdf:resource=""/>

Another way is to use the owl:sameAs predicate.

<ot:Algorithm rdf:ID="AlgorithmSVM">
    <owl:sameAs rdf:resource=""/>
In case of the Algorithms, it seems it is more appropriate to use ot:isA predicate, since it better describes the desired statement "AlgorithmSVM is a Regression algorithm"

The OpenTox API ontology makes use of ot:isA predicate.

More examples available here




Triple stores



•Multiple languages

•Java,, restlet > 2.0, VRP, more

Protege can generate Java interfaces, given a data model (owl. file).  Here are the interfaces, generated for OpenTox.owl