wiki:OntologyOfNeuroanatomy

Version 4 (modified by detwiler, 8 years ago) (diff)

--

A basic requirement for facilitating the integration and analysis of basic and clinical neuroscientific data from diverse sources is a well-structured ontology that can incorporate and organize all kinds of neuroanatomical data into a knowledge base that can lend support and extend to the demands of existing and evolving multi-scale neuroscience and clinical applications. Here we show how the Foundational Model of Anatomy (FMA) Ontology (http://sig.biostr.washington.edu/projects/fm/AboutFM.html) as a reference ontology can provide a structure-based foundation for a neuroanatomy ontology and therefore endowing it with a semantic framework capable of explicitly defining any neuroanatomical types and thus facilitating correlation of different and disparate neuroanatomical views, a requirement necessary for aligning existing and emerging ontologies and theories used in neuroinformatics.

Related publication:

Mejino, Jose L V and Martin, Richard F and Detwiler, Landon T and Brinkley, James F (2007) Challenges in Reconciling Different Views of Neuroanatomy in a Reference Ontology of Anatomy. In Proceedings, American Medical Informatics Association Fall Symposium, Chicago, IL.

http://sigpubs.biostr.washington.edu/archive/00000214/03/MejinoAMIA2007Poster.pdf

http://sigpubs.biostr.washington.edu/archive/00000214/04/Mejino2007PosterSupplement.pdf

Query:

PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>
PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX owl:<http://www.w3.org/2002/07/owl#>
PREFIX gleen:<java:edu.washington.sig.gleen.>
PREFIX temp:<http://sig.biostr.washington.edu/temp#>
PREFIX fma:<http://sig.biostr.washington.edu/fma3.0#>

####################################################################################
# Generate the NeuroFMA
####################################################################################
CONSTRUCT {  ?x ?y ?z }
FROM <http://sig.biostr.washington.edu/fma3.0>

# all parts recursively of neuraxis
FROM NAMEDV <top_pre_neuraxis_parts> [
    CONSTRUCT {temp:set temp:member ?part}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE {fma:Neuraxis gleen:OnPath ("([fma:regional_part]|[fma:constitutional_part])*" ?part)}
]
FROM NAMEDV <pre_neuraxis_parts> [
     CONSTRUCT {temp:set temp:member ?part . temp:set temp:member ?c. }
     FROM NAMEDV <top_pre_neuraxis_parts>
     FROM <http://sig.biostr.washington.edu/fma3.0>
     WHERE { GRAPH <top_pre_neuraxis_parts> { ?a ?b ?part } . 
	     OPTIONAL { ?part rdf:type ?c } }
]

# get all inter-part attributed relationship instances (and rels)
FROM NAMEDV <neuraxis_attr_rels_in> [
   CONSTRUCT {?p ?rel ?q}
   FROM <http://sig.biostr.washington.edu/fma3.0>
   WHERE { GRAPH <pre_neuraxis_parts> {temp:set temp:member ?p.}.
           ?p ?rel ?q.
           OPTIONAL {?q rdfs:subClassOf ?super}. FILTER(!bound(?super)).
           FILTER((?rel = fma:attributed_part) || (?rel = fma:related_part)). }
]

# get all inter-part attributed relationship instances (and rels)
FROM NAMEDV <neuraxis_attr_rels_out> [
   CONSTRUCT {?q ?rel2 ?p2.}
   FROM <http://sig.biostr.washington.edu/fma3.0>
   WHERE { GRAPH <pre_neuraxis_parts> {temp:set temp:member ?p2.}.
           ?q ?rel2 ?p2.
           OPTIONAL {?q rdfs:subClassOf ?super}. FILTER(!bound(?super)).
           FILTER((?rel2 = fma:attributed_part) || (?rel2 = fma:related_part)). }
]

# get all inter-part attributed relationship instances (and rels)
FROM NAMEDV <neuraxis_attr_rels> [
   CONSTRUCT {temp:set temp:member ?q. 
	      temp:rel_set temp:member ?rel. 
	      temp:rel_set temp:member ?rel2.}
   FROM <http://sig.biostr.washington.edu/fma3.0>
   WHERE { GRAPH <neuraxis_attr_rels_in> {?p ?rel ?q.}.
           GRAPH <neuraxis_attr_rels_out> {?q ?rel2 ?p2.}. }
]

# get all inter-part attributed instances types 
FROM NAMEDV <neuraxis_parts> [
	CONSTRUCT {temp:set temp:member ?p. 
		  temp:set temp:member fma:Concept_name.
		  temp:set temp:member fma:Query_Atlas_term.
		  temp:set temp:member fma:Neurolex_term.
		  temp:set temp:member fma:AAL_term. }
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE { { GRAPH <pre_neuraxis_parts> {temp:set temp:member ?p}
    	    } UNION {
	      GRAPH <neuraxis_attr_rels> {temp:set temp:member ?q.}
   	      ?q rdf:type ?p.
   	    } }
]

# build graph containing all properties of all classes identified so far
FROM NAMEDV <neuraxis_parts_graph> [
    CONSTRUCT {?p ?rel ?obj}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE {GRAPH <neuraxis_parts> {temp:set temp:member ?p}. ?p ?rel ?obj .}
]

# get all properties which either connect two of the parts above or connects a part to a literal
FROM NAMEDV <neuraxis_parts_props> [
	CONSTRUCT { temp:set temp:member ?b. 
		    temp:set temp:member ?e. 
		    temp:set temp:member ?rel.
		    temp:set temp:member fma:Preferred_name.
		    temp:set temp:member fma:Synonym.
		    temp:set temp:member fma:Non-English_equivalent.
		    temp:set temp:member fma:Query_Atlas.
		    temp:set temp:member fma:Neurolex.
		    temp:set temp:member fma:AAL. }
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE { { GRAPH <neuraxis_parts_graph> {?a ?b ?c}. FILTER isLiteral(?c) 
	    } UNION {
	      GRAPH <neuraxis_parts_graph> {?d ?e ?f}.
	      GRAPH <neuraxis_parts> {temp:set temp:member ?f}.
	    } UNION {
	      GRAPH <neuraxis_attr_rels> {temp:rel_set temp:member ?rel.}
	    } }
]

# Our view only includes a small number of Non-physical_anatomical_entity_template
# (and subClass) instances. Build up a list of things to exclude.
FROM NAMEDV <stoppingPoint> [
     CONSTRUCT { temp:set temp:member ?a .}
     FROM <http://sig.biostr.washington.edu/fma3.0>     
     WHERE { ?a gleen:OnPath ("[rdfs:subClassOf]*" fma:Non-physical_anatomical_entity_template) . }
]
FROM NAMEDV <exclusionTypes> [
     CONSTRUCT { temp:set temp:member ?b }
     FROM <http://sig.biostr.washington.edu/fma3.0>     
     WHERE { GRAPH <stoppingPoint> { ?ts ?tm ?a . }
	     ?b rdf:type ?a .
	     FILTER ( ?b != fma:AAL_term && 
		    ?b != fma:Concept_name &&
		    ?b != fma:Neuro_term &&
		    ?b != fma:Neurolex_term &&
		    ?b != fma:Non-physical_anatomical_entity_template &&
		    ?b != fma:Organ_part_of_relationship_value &&
		    ?b != fma:Organ_subdivision_part_of_relationship_value &&
		    ?b != fma:Part_of_relationship_value &&
		    ?b != fma:Query_Atlas_term &&
		    ?b != fma:Structural_relationship_value ) . }
]

# determine superclasses, superproperties, and types
# add nodes connected to blank nodes and recurse on these
FROM NAMEDV <pre_neuraxis_parts_ext> [
    CONSTRUCT {temp:set temp:member ?c.}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    FROM NAMEDV <exclusionTypes>
    WHERE { { GRAPH <neuraxis_parts> {temp:set temp:member ?c}. 
	      OPTIONAL {GRAPH <exclusionTypes> {?ts temp:member ?c}.}. FILTER (!bound(?ts)) .
	    } UNION {
		GRAPH <neuraxis_parts_props> {temp:set temp:member ?c}.
		OPTIONAL {GRAPH <exclusionTypes> {?ts temp:member ?c}.}. FILTER (!bound(?ts)) .
	    } }
    UNION
    CONSTRUCT {temp:set temp:member ?v.}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    FROM NAMEDV <exclusionTypes>
    FROM NAMEDV <pre_neuraxis_parts_ext>
    WHERE { GRAPH <pre_neuraxis_parts_ext> {temp:set temp:member ?c.}
            {?c rdf:type ?v.} UNION {?c rdfs:subClassOf ?v} UNION {?c rdfs:subPropertyOf ?v} UNION
            {?c ?rel ?v. FILTER (isBlank(?c) && !isLiteral(?v)).}.
            OPTIONAL {GRAPH <exclusionTypes> {?ts temp:member ?v}.} . FILTER (!bound(?ts)) . }
]

# add in attributed instances
FROM NAMEDV <neuraxis_parts_ext> [
    CONSTRUCT {temp:set temp:member ?p. temp:set temp:member ?q. temp:set temp:member ?cn.}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE { { GRAPH <pre_neuraxis_parts_ext> {temp:set temp:member ?p}. 
              OPTIONAL { {?p fma:Preferred_name ?cn.}UNION
                         {?p fma:Synonym ?cn.}UNION
                         {?p fma:Non-English_equivalent ?cn.}UNION
		         {?p fma:Query_Atlas ?cn.}UNION
		         {?p fma:Neurolex ?cn.}UNION
		         {?p fma:AAL ?cn.} }
    	    } UNION {
    	      GRAPH <neuraxis_attr_rels> {temp:set temp:member ?q}.
    	    } }
]

# build graph containing all properties of all classes identified so far
FROM NAMEDV <neuraxis_parts_ext_graph> [
    CONSTRUCT {?p ?rel ?obj}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE {GRAPH <neuraxis_parts_ext> {temp:set temp:member ?p}. ?p ?rel ?obj .}
]

# build graph containing only properties connecting two classes in ext or a class in ext to a literal
FROM NAMEDV <neuraxis_view_wo_props> [
    CONSTRUCT {?a ?b ?c. ?d ?e ?f.}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE { { GRAPH <neuraxis_parts_ext_graph> {?a ?b ?c}. FILTER isLiteral(?c) 
            } UNION {
	      GRAPH <neuraxis_parts_ext_graph> {?d ?e ?f}.
	      GRAPH <neuraxis_parts_ext> {temp:set temp:member ?f}.
	    } }
]


# determine superclasses, superproperties, and types
# add nodes connected to blank nodes and recurse on these
FROM NAMEDV <pre_neuraxis_parts_props_ext> [
    CONSTRUCT {temp:set temp:member ?c.}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE  { { # we need to define all of the properties that are going to be held in the result graph
		GRAPH <neuraxis_view_wo_props> { ?uns ?c ?uno }
	     } UNION { # see if we had any restrictions on properties; if we did, we need to define those properties fully 
		GRAPH <pre_neuraxis_parts_ext> {temp:set temp:member ?c}. 
		?r rdf:type owl:Restriction . ?r owl:onProperty ?c .
	     } UNION {
		GRAPH <neuraxis_parts_props> {temp:set temp:member ?c}.
	     } }
    UNION
    CONSTRUCT {temp:set temp:member ?v.}
    FROM <http://sig.biostr.washington.edu/fma3.0>
    FROM NAMEDV <pre_neuraxis_parts_props_ext>
    WHERE { GRAPH <pre_neuraxis_parts_props_ext> {temp:set temp:member ?c.}
            {?c rdf:type ?v.} UNION {?c rdfs:subClassOf ?v} UNION {?c rdfs:subPropertyOf ?v} UNION
            {?c ?rel ?v. FILTER (isBlank(?c) && !isLiteral(?v)).}. }
]

FROM NAMEDV <rec_pre_neuraxis_parts_props_ext> [
     CONSTRUCT { ?c ?d ?e }
     FROM <http://sig.biostr.washington.edu/fma3.0>
     WHERE { GRAPH <pre_neuraxis_parts_props_ext> { temp:set temp:member ?c } .
	     ?c ?d ?e . 
	     OPTIONAL {GRAPH <neuraxis_parts_ext> { ?ts temp:member ?e } } .
	     FILTER (isBlank(?e) || isLiteral(?e) || bound(?ts) ||
		    (!bound(?ts) && !regex(str(?e),"http://sig.biostr.washington.edu/fma3.0")) ). }
     UNION
     CONSTRUCT { ?e ?f ?g }
     FROM <http://sig.biostr.washington.edu/fma3.0>
     FROM NAMEDV <rec_pre_neuraxis_parts_props_ext> 
     WHERE { GRAPH <rec_pre_neuraxis_parts_props_ext> { ?c ?d ?e } .FILTER isBlank(?e) .
	     ?e ?f ?g . 
	     OPTIONAL {GRAPH <neuraxis_parts_ext> { ?ts temp:member ?g } .} .
	     FILTER (isBlank(?g) || isLiteral(?g) || bound(?ts) ||
		    (!bound(?ts) && !regex(str(?g),"http://sig.biostr.washington.edu/fma3.0")) ). }
]

FROM NAMEDV <neuraxis_view> [
    CONSTRUCT {?a ?b ?c. ?d ?e ?f.
	?ontS ?ontP owl:Ontology . ?ontS ?anyOntP ?anyOntO .
    }
    FROM <http://sig.biostr.washington.edu/fma3.0>
    WHERE { { GRAPH <neuraxis_view_wo_props> {?a ?b ?c}.
	    } UNION {
	      GRAPH <rec_pre_neuraxis_parts_props_ext> {?d ?e ?f}.
	    } UNION {
	      ?ontS ?ontP owl:Ontology .
	      OPTIONAL { ?ontS ?anyOntP ?anyOntO . }
            } }
]

####################################################################################
# Fixup the generated NeuroFMA
####################################################################################


# Find all of the RDF list nodes that do not have an element; 
# recursively follow the list until it either hits a node with
# an element or it hits rdf:nil. Track the node that points
# to this errant list and the entire set of reachable nodes
# before the errant list has an element.
FROM NAMEDV <identify_rdfListEmptyNodes> [
    CONSTRUCT { ?a rdf:rest ?b .	# to be changed
	        ?b temp:rest ?c . 	# to be deleted
	        ?a temp:starts ?b .	# first node in rest list
	        ?a temp:reaches ?c . 	# reachability list
    }
    FROM NAMEDV <neuraxis_view>
    WHERE { GRAPH <neuraxis_view> {
                ?a rdf:first ?noop .
                ?a rdf:rest ?b .
                OPTIONAL { ?b rdf:first ?a_bogus } . FILTER(!bound(?a_bogus)) .
                ?b rdf:rest ?c . 
            } }
    UNION
    CONSTRUCT { ?a ?pred ?b .	# to be changed
	        ?b temp:rest ?c .	# to be deleted
	        ?a temp:starts ?b . # first node in rest list
	        ?a temp:reaches ?c . # reachability list
    }
    FROM NAMEDV <neuraxis_view>
    WHERE { GRAPH <neuraxis_view> {
    	        ?a ?pred ?b . FILTER(?pred != rdf:rest) .
    	        ?b rdf:rest ?c . 
	        OPTIONAL { ?b rdf:first ?b_bogus } . FILTER(!bound(?b_bogus)) .
            } }
    UNION
    CONSTRUCT { ?c temp:rest ?d .	# to be deleted
	        ?a temp:reaches ?d . # reachability list
    }
    FROM NAMEDV <identify_rdfListEmptyNodes>
    FROM NAMEDV <neuraxis_view>
    WHERE { GRAPH <identify_rdfListEmptyNodes> { ?a temp:reaches ?c . } .
            GRAPH <neuraxis_view> {
	      OPTIONAL { ?c rdf:first ?noop } . FILTER(!bound(?noop)) .
	      ?c rdf:rest ?d . 
          } }
]

# Eliminate all of the edges corresponding to RDF lists elements with no value
FROM NAMEDV <remove_rdfListEmptyNodes> [
     CONSTRUCT { ?x ?y ?z . }
     FROM NAMEDV <identify_rdfListEmptyNodes>
     FROM NAMEDV <neuraxis_view>
     WHERE { GRAPH <neuraxis_view> { ?x ?y ?z . }
	     OPTIONAL { GRAPH <identify_rdfListEmptyNodes> { ?x ?ynot ?z } . 
	   	        FILTER(?ynot=temp:rest && ?y=rdf:rest) } . 
             FILTER(!bound(?ynot)) . }
]

# Remove all of the edges to the start of RDF lists containing empty nodes; 
# we replace these edges with new edges in <add_startEdgeRdfListEmptyNodes>
FROM NAMEDV <remove_startEdgeRdfListEmptyNodes> [
     CONSTRUCT { ?q ?r ?s .}
     FROM NAMEDV <identify_rdfListEmptyNodes> 
     FROM NAMEDV <remove_rdfListEmptyNodes>
     WHERE { GRAPH <remove_rdfListEmptyNodes> { ?q ?r ?s . } .
	     OPTIONAL { GRAPH <identify_rdfListEmptyNodes> { ?q ?r ?t } . FILTER(?s = ?t) } .
	     FILTER(!bound(?t)) . }
]

# Add in the new edges to the RDF lists containing empty nodes
FROM NAMEDV <add_startEdgeRdfListEmptyNodes> [
     CONSTRUCT { ?t ?u ?v .
	         ?a2 ?pred2 ?d2 .
     }
     FROM NAMEDV <identify_rdfListEmptyNodes>
     FROM NAMEDV <remove_startEdgeRdfListEmptyNodes>
     FROM NAMEDV <neuraxis_view>
     WHERE { { GRAPH <remove_startEdgeRdfListEmptyNodes> { ?t ?u ?v  }
             } UNION {
	       GRAPH <identify_rdfListEmptyNodes> { 
	     	   ?a2 temp:starts ?b2 .
	     	   ?a2 ?pred2 ?gone2 . 
		   FILTER(!REGEX(str(?pred2),"http://sig.biostr.washington.edu/temp#") ) .
		   ?a2 temp:reaches ?d2 . }
  	       GRAPH <neuraxis_view> { OPTIONAL {  ?d2 rdf:first ?nxt2 } . }
	       FILTER( (?d2 = rdf:nil) || bound(?nxt2) ) . 
             } }
]

########################################################################################
########################################################################################

# Find owl:unionOf statements that have RDF lists of 0 or 1 elements.
# Replace the owl:unionOf statements with either the element or rdf:nil.
FROM NAMEDV <removed_shortUnionOfs> [
     CONSTRUCT { ?q ?r ?s .
	         ?before1 ?pred1 ?c1 .
	         ?before2 ?pred2 rdf:nil .
     }
     FROM NAMEDV <add_startEdgeRdfListEmptyNodes> 
     # Find owl:unionOfs that have 0 or 1 element.
     FROM NAMEDV <identify_shortUnionOfs> [
          CONSTRUCT { 
	      ?before1 ?pred1 ?a1 .
	      ?a1 owl:unionOf ?b1 .
	      ?a1 rdf:type owl:Class .
	      ?b1 rdf:first ?c1 .
	      ?b1 rdf:rest rdf:nil .
	      ?before2 ?pred2 ?a2 .
	      ?a2 owl:unionOf ?b2 .
	      ?a2 rdf:type owl:Class .
	      ?b2 rdf:rest rdf:nil .
         }
         FROM NAMEDV <add_startEdgeRdfListEmptyNodes> 
     	 WHERE { { GRAPH <add_startEdgeRdfListEmptyNodes> {
			?before1 ?pred1 ?a1 .
	        	?a1 owl:unionOf ?b1 .
	        	?a1 rdf:type owl:Class .
	        	?b1 rdf:first ?c1 .
	        	?b1 rdf:rest rdf:nil .
		   }
                 } UNION {
		   GRAPH <add_startEdgeRdfListEmptyNodes> {
 	           	?before2 ?pred2 ?a2 .
	        	?a2 owl:unionOf ?b2 .
	        	?a2 rdf:type owl:Class .
	        	OPTIONAL { ?b2 rdf:first ?c2 . } . FILTER(!bound(?c2)) .
	        	?b2 rdf:rest rdf:nil .
                   }
	         } }
     ]
     WHERE { { GRAPH <add_startEdgeRdfListEmptyNodes> { ?q ?r ?s . }
     	       OPTIONAL { GRAPH <identify_shortUnionOfs> { ?q ?r ?t . FILTER(?s = ?t) } }
	       FILTER(!bound(?t)) .
             } UNION {
	       GRAPH <identify_shortUnionOfs> {
	     	   ?before1 ?pred1 ?a1 .
		   ?a1 owl:unionOf ?b1 .
		   ?b1 rdf:first ?c1 . 
		   ?b1 rdf:rest rdf:nil .
	       }
             } UNION {
	       GRAPH <identify_shortUnionOfs> {
	     	   ?before2 ?pred2 ?a2 .
		   ?a2 owl:unionOf ?b2 .
		   OPTIONAL { ?b2 rdf:first ?c2 . } . FILTER(!bound(?c2)) . }
		   ?b2 rdf:rest rdf:nil .
	     } }
]

########################################################################################
########################################################################################

# Remove all owl:allValuesFrom that have empty owl:unionOf lists.
FROM NAMEDV <remove_emptyAllValuesFrom> [
     CONSTRUCT { ?a ?b ?c . }
     FROM NAMEDV <removed_shortUnionOfs> 

     # identify allValuesFrom with empty RDF lists
     FROM NAMEDV <identify_emptyAllValuesFrom> [
         CONSTRUCT { ?x owl:allValuesFrom ?allB .
	             ?allB rdf:type owl:Class .
	             ?allB owl:unionOf rdf:nil .
         }
         FROM NAMEDV <removed_shortUnionOfs> 
         WHERE { GRAPH <removed_shortUnionOfs> {
                     ?x owl:allValuesFrom ?allB .
                     ?allB rdf:type owl:Class .
                     ?allB owl:unionOf rdf:nil .
                 } }
     ]
     WHERE { GRAPH <removed_shortUnionOfs> { ?a ?b ?c . }
	     OPTIONAL { GRAPH <identify_emptyAllValuesFrom> { ?a ?b ?cnot . FILTER(?c=?cnot) } } .
	     FILTER(!bound(?cnot)) . }
]

########################################################################################
########################################################################################

# remove the set of owl:Restrictions that do not have values associated with
# owl:onProperty restrictions
FROM NAMEDV <remove_emptyOwlOnPropertyRestrictions> [
     CONSTRUCT { ?a ?b ?c . }
     FROM NAMEDV <remove_emptyAllValuesFrom> 
     # identify the set of owl:Restrictions that do not have values associated with
     # owl:onProperty restrictions
     FROM NAMEDV <identify_emptyOwlOnPropertyRestrictions> [
         CONSTRUCT { ?x rdfs:subClassOf ?owlrestrict .
	             ?owlrestrict rdf:type owl:Restriction .
	             ?owlrestrict owl:onProperty ?onprop .
         }
         FROM NAMEDV <remove_emptyAllValuesFrom> 
         WHERE { 
	          GRAPH <remove_emptyAllValuesFrom> {
  	       	       ?x rdfs:subClassOf ?owlrestrict .
		       ?owlrestrict rdf:type owl:Restriction .
   	     	       ?owlrestrict owl:onProperty ?onprop .
	     	       OPTIONAL { ?owlrestrict ?anyp ?anyo . 
		       		  FILTER((?anyp!=rdf:type)&&(?anyp!=owl:onProperty)) . }
	               FILTER(!bound(?anyp)) . 
                  } }
      ]
      WHERE { GRAPH <remove_emptyAllValuesFrom> { ?a ?b ?c . }
	      OPTIONAL { GRAPH <identify_emptyOwlOnPropertyRestrictions> { ?a ?b ?cnot . FILTER(?c=?cnot) } } .
	      FILTER(!bound(?cnot)) . }
]
WHERE {	GRAPH <remove_emptyOwlOnPropertyRestrictions> { ?x ?y ?z } }