How to properly load SNOMED Ontology

Dear community,

I am working on my PhD in clinical decision support. Currently, I am analysing the knowledge obtained in the SNOMED CT regarding birth outcomes - I would like to follow this blog Using SNOMED in Stardog | Stardog. I do not know how to correctly import the SNOMED CT ontology into Stardog database, as I am seeing too many strange components after import, without proper SNOMED CT/rdfs labels such as rdfs:subClassOf

  • bnode_7d17f434_7562_45d9_aa73_6612bed6497a_1144218 - I would expect proper SNOMED CT class with a readable label.

I have converted SNOMED CT RF2 file to OWL, using the tool provided by SNOMED CT GitHub - IHTSDO/snomed-owl-toolkit: The official SNOMED CT OWL Toolkit. OWL conversion, classification and authoring support., then I opened the owl file in Protege and saved it as RDF/XML file. Afterwards, I loaded it into an empty Stardog database.

Thanks a lot in advance for your help and insights,

Kind regards,


Some owl rule heavily relie on blank node (of format bnode_....). Let assume that I want the following rule

the data property givenName can be inferred from vcard:n/vcard:given-name. When you first write the rules it would look something liek

ex:givenName a owl:DataProperty ;
   owl:propertyChainAxiom ( (vcard:n vcard:given-name) .

Still fairly easy to read. However if I load in Stardog, and I export the a turtle file, it would now be represented with something that look like this

ex:givenName a owl:DataProperty ;
   owl:propertyChainAxiom _:bnode_cff48394_5ac4_4425_9da7_bd61ce5fd98b_186 , _:bnode_cff48394_5ac4_4425_9da7_bd61ce5fd98b_202 , _:bnode_cff48394_5ac4_4425_9da7_bd61ce5fd98b_218 , _:bnode_cff48394_5ac4_4425_9da7_bd61ce5fd98b_234 .
_:bnode_cff48394_5ac4_4425_9da7_bd61ce5fd98b_186 rdf:first vcard:n ;
   rdf:rest _:bnode_cff48394_5ac4_4425_9da7_bd61ce5fd98b_187 .
_:bnode_cff48394_5ac4_4425_9da7_bd61ce5fd98b_187 rdf:first vcard:given-name ;
   rdf:rest rdf:nil .

Notice all the _:bnode. Having many such thing does not necessarily mean there is a problem.

Dear Serge, thanks a lot for explanation. It really seems that it loaded well (please refer to the picture) and that various restrictions are stored in these blank nodes (anonymous OWL classes). But please, is there some help how to run SPARQL queries when you have so many nonstandard classes = these bnode_ ones and nested class expressions? The textbook SPARQL examples are of no use.

I would need more info to help. However here a starting point to help you. Let's take the vcard example given here: Representing vCard Objects in RDF

  @prefix rdf:  <> .
  @prefix v:  <> .

  <> a v:VCard ;
     v:fn "Corky Crystal" ;
     v:nickname "Corks" ;
         [ a v:Home, v:Voice ;
             rdf:value "+61 7 5555 5555"
         ] ; 
     v:email  <> ;
         [ a v:Home ;
             v:country-name "Australia" ;
             v:locality "WonderCity" ;
             v:postal-code "5555" ;
             v:street-address "111 Lake Drive"
         ] .

This record uses two bnode, one for v:tel and one for v:addr. If you simply want the phone and city of Corky you could use the following SPARQL

SELECT ?phone ?city
   _:s v:fn "Corky Crystal" ;
       v:tel/rdf:value ?phone .
       v:adr/v:locality ?city .

Notice I used property path for convenience, essentially this query is the same as the following

   _:s v:fn "Corky Crystal" ;
       v:tel _:tel;                 #get the bnode for tel
       v:adr _:adr;             #get the bnode for adr

   _:tel rdf:value ?phone .
   _:adr v:locality ?city .

In other word, you simply need to traverse across the bnodes.

Now if for instance I add the following PropertyPathAxiom I mentioned in the previous response

ex:phone a owl:DataProperty ;
   owl:propertyChainAxiom ( (v:tel rdf:value) .

ex:city a owl:DataProperty ;
   owl:propertyChainAxiom ( (v:adr v:locality) .

When this is loaded it it will create several bnode, but in this case the bnode are an implementation detail and you do not need to worry about them in your query since the reasoner will handle everything for you under the cover. Therefore now if you want Corky phone number you simply need the following SPARQL query

          _:s v:fn "Corky Crystal" ;
               ex:phone ?phone ;
               ex:city ?city .

In summary, if the blank node are part of your data structure, simply traverse as needed, if the blank node are part of your OWL definition, ignore them as your reasoner will handle everything for you.

This is one of the reason, I usually load the RDFS & OWL rules in a different namespace than my actual data.

1 Like

Thanks a lot, Sege, this is very helpful :wink:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.