Custom properties of OWL/RDF Ontology

Hi,

I am trying to import an ontology, which is in RDF/XML format (owl):

call n10s.graphconfig.init( { keepCustomDataTypes:true, handleRDFTypes: "LABELS_AND_NODES" });
CALL n10s.onto.import.fetch("...","RDF/XML");

In the ontology file, each class contains synonym properties:

<oboInOwl:hasExactSynonym rdf:datatype="http://www.w3.org/2001/XMLSchema#string">human mammary epithelial cell</oboInOwl:hasExactSynonym>

However the nodes of type Class do not contain that custom properties, and also separate nodes are not created. How can I get those custom proprieties into Neo4J?

Best,
Maksims

Hi @maksims.fiosins, If you want to keep your ontology simple, all you need to do is add to your script an additional step to import the extra properties using n10s.rdf.stream. Here's what it would look like if you wanted to add the oboInOwl:hasExactSynonym property to the imported classes:

CALL n10s.rdf.stream.fetch("...your onto...","RDF/XML") YIELD subject, predicate, object
WHERE predicate = "http://www.geneontology.org/formats/oboInOwl#hasExactSynonym"
MATCH (c:Class { uri: subject }) SET c.exactSynonym = coalesce(c.exactSynonym,[]) + [ object ]

With n10s.rdf.stream you can take control on how to handle each individual triple and decide how you want to model it. Check out the manual for more examples.

Another alternative would be to load the ontology as RDF with n10s.rdf.import. That way you'd be importing every single triple in the ontology as opposed to the simplified model that n10s.onto.import builds. It really depends on how you're going to use your ontology.

Let us know if this works for you.

Cheers,

JB.

Hi @jesus_barrasa,

Thank You for Your quick answer, the stream idea is very helpful. However, if I do
n10s.rdf.stream.fetch, I get first 1000 triples. The manual does not say anything about this limit. Maybe You have an idea why this happens?

Best,
Maksims

Oh, thanks for bringing this to our attention, we're updating the manual and this is clearly a missing element. The request config parameter is limit and you can add it like this:

call n10s.rdf.stream.fetch('url','RDF/XML,{ limit: 999999999 })

And yes, if not set, the default value is 1000.

Hope this helps.

JB.

1 Like

Hi @jesus_barrasa,

Thank You for Your reply. The limit really helps.
So now I have the following fragment, which loads my ontology with synonyms as separate nodes:

CALL n10s.graphconfig.init();
CALL n10s.onto.import.fetch("...my ontology file ...","RDF/XML");
CREATE INDEX FOR (n:Class) ON (n.uri)
CALL n10s.rdf.stream.fetch("...my ontology file ...","RDF/XML",{ limit: 999999999 }) YIELD subject, predicate, object
WHERE predicate = "http://www.geneontology.org/formats/oboInOwl#hasExactSynonym"
MATCH (c:Class { uri: subject }) 
MERGE (c)-[r:SynonymRel]-(s:Synonym{rdfs__label:object});
1 Like

However, I have one more problem. Namely, there is a partOf relation in the ontology, which is defined by two predicates:

<owl:Class rdf:about="<uri of a class>">
        <rdfs:subClassOf>
            <owl:Restriction>
                <owl:onProperty rdf:resource="<uri of partOf predicate>"/>
                <owl:someValuesFrom rdf:resource="<uri of a parent>"/>
            </owl:Restriction>
        </rdfs:subClassOf>
...
</owl:Class>

By streaming this using n10s.rdf.stream.fetch I get the triples one by one. When I am on the triple

                <owl:someValuesFrom rdf:resource="<uri of a parent>"/>

how can I get:

  • A triple <owl:onProperty rdf:resource="<uri of partOf predicate>"/>, because from it I know that this is a "partOf" relation;

  • A parent <owl:Class rdf:about="<uri of a class>">, because from it I get uri of the main class.

Maybe it is possible to get a predefined type structure or to access parent/sister triples?

Best regards,
Maksims

Great question @maksims.fiosins !

First option would be to use SPARQL. If the ontology lives in a repository that offers SPARQL access you can write a query that returns just the fragment you're looking for. Then you could embed your SPARQL endpoint request in the n10s.rdf.stream.fetch procedure call as described in the manual. But I understand SPARQL access is not always available and you may be just fetching a document containing all the triples.

Alternatively, we'd need to include that logic in the n10s.onto.import procedures. I've been looking at this for a while (how to extend the elements in the ontology that the onto.import loads in order to include constructs like Restriction definitions) but could not come up with a satisfactory solution that was useful and did not involve a massive effort.

I'd love to hear your thoughts on this second option. How would you want the restriction in your example modelled in the graph? Or maybe from a different angle: how do you intend to use it once loaded in neo4j?

Cheers,

JB.

Dear @jesus_barrasa,

Thank You again for Your answer.

SPARQL will not solve the problem, because the problem is not to select the necessary triples - I can do it using WHERE - but to transform the structure. I am not sure, if SPARQL allows this.

In the meantime I solved the problem with a parent by saving child subject id in the node.

CALL n10s.rdf.stream.fetch('file:////var/lib/neo4j/import/%s.owl','RDF/XML',{ limit: 999999999 })
                          YIELD subject,predicate,object
                          WHERE predicate IN ['http://www.w3.org/2000/01/rdf-schema#subClassOf','http://www.w3.org/2002/07/owl#someValuesFrom']
                          CALL apoc.do.when(predicate='http://www.w3.org/2000/01/rdf-schema#subClassOf',
                                 'MATCH (c:Class {uri:subject}) SET c.subClassOf=object RETURN c',
                                 'MATCH(c:Class{subClassOf:subject}) MATCH (p:Class{uri:object})
                                  MERGE (c)-[:SCO]->(p) RETURN c', {subject:subject,predicate:predicate,object:object}) YIELD value RETURN value"""

Here I do not use a sister predicate, I assume that subClassOf already points to the parent hierarchy.

I think n10s.onto.import may be extended that it at least allows other predicates to be used in the ontology graph creation. However I don't have currently a good suggestion about the syntax, it requires some complex structures to describe how the hierarchy and the labels are created.

Best regards,
Maksims

It is indeed possible to change the structure of the RDF graph with SPARQL CONSTRUCT.
Here's a repository where I use it extensively to import data from Wikidata and MeSH into Neo4j, the recording of the presentation is here.

Regards,

JB.