Query, inspect and visualize ontologies encoded via RDF and OWL.
—
Ontospy provides comprehensive SPARQL query capabilities for programmatic ontology interrogation and analysis. The SPARQL helper system offers both direct query execution and specialized methods for common ontological analysis patterns.
Execute SPARQL queries directly against loaded RDF graphs or remote SPARQL endpoints.
# Main Ontospy class query methods
def query(self, sparql_query):
"""
Execute SPARQL query against loaded RDF graph.
Parameters:
- sparql_query (str): SPARQL query string
Returns:
rdflib.plugins.sparql.processor.SPARQLResult: Query results with iteration support
"""
def sparql(self, sparql_query):
"""Alias for query() method providing SPARQL execution."""Usage Examples:
import ontospy
# Load ontology
g = ontospy.Ontospy("ontology.owl", build_all=True)
# Simple SELECT query
results = g.query("""
SELECT ?class ?label WHERE {
?class a rdfs:Class .
OPTIONAL { ?class rdfs:label ?label }
}
LIMIT 10
""")
# Process results
for row in results:
print(f"Class: {row.class}, Label: {row.label}")
# COUNT query
count_result = g.query("""
SELECT (COUNT(?class) as ?classCount) WHERE {
?class a rdfs:Class
}
""")
for row in count_result:
print(f"Total classes: {row.classCount}")
# CONSTRUCT query
graph_result = g.query("""
CONSTRUCT { ?class rdfs:subClassOf ?parent } WHERE {
?class rdfs:subClassOf ?parent .
?class a rdfs:Class .
?parent a rdfs:Class
}
""")
# Resulting graph can be serialized
print(graph_result.serialize(format="turtle"))Specialized helper class providing optimized queries for common ontological analysis patterns.
from ontospy.core.sparql_helper import SparqlHelper
class SparqlHelper:
def __init__(self, rdfgraph, sparql_endpoint=False):
"""
Initialize SPARQL helper for ontology analysis.
Parameters:
- rdfgraph (rdflib.Graph): RDF graph to query
- sparql_endpoint (bool): Flag indicating remote endpoint usage
"""Extract ontology declarations and metadata using specialized query methods.
def getOntology(self):
"""
Extract ontology instances and declarations.
Returns:
list: Ontology URIs and associated metadata
"""Comprehensive class analysis including hierarchy extraction, instance counting, and relationship mapping.
def getAllClasses(self, hide_base_schemas=True, hide_implicit_types=True):
"""
Extract all class definitions from ontology.
Parameters:
- hide_base_schemas (bool): Filter out base vocabulary (RDF, RDFS, OWL)
- hide_implicit_types (bool): Filter implicit type declarations
Returns:
list: Class URIs with metadata
"""
def getClassInstances(self, aURI):
"""
Get all instances of specified class.
Parameters:
- aURI (str): Class URI
Returns:
list: Instance URIs that are members of the class
"""
def getClassInstancesCount(self, aURI):
"""
Count instances of specified class.
Parameters:
- aURI (str): Class URI
Returns:
int: Number of class instances
"""
def getClassDirectSupers(self, aURI):
"""
Get immediate superclasses of specified class.
Parameters:
- aURI (str): Class URI
Returns:
list: Direct parent class URIs
"""
def getClassDirectSubs(self, aURI):
"""
Get immediate subclasses of specified class.
Parameters:
- aURI (str): Class URI
Returns:
list: Direct child class URIs
"""
def getClassAllSupers(self, aURI):
"""
Get all superclasses (transitive closure).
Parameters:
- aURI (str): Class URI
Returns:
list: All ancestor class URIs
"""
def getClassAllSubs(self, aURI):
"""
Get all subclasses (transitive closure).
Parameters:
- aURI (str): Class URI
Returns:
list: All descendant class URIs
"""Extract property definitions, hierarchies, and domain/range relationships.
def getAllProperties(self, hide_implicit_preds=True):
"""
Extract all property definitions.
Parameters:
- hide_implicit_preds (bool): Filter implicit predicate declarations
Returns:
list: Property URIs with type information
"""
def getPropDirectSupers(self, aURI):
"""
Get immediate superproperties.
Parameters:
- aURI (str): Property URI
Returns:
list: Direct parent property URIs
"""
def getPropAllSupers(self, aURI):
"""
Get all superproperties (transitive closure).
Parameters:
- aURI (str): Property URI
Returns:
list: All ancestor property URIs
"""
def getPropAllSubs(self, aURI):
"""
Get all subproperties (transitive closure).
Parameters:
- aURI (str): Property URI
Returns:
list: All descendant property URIs
"""
def getPropsApplicableByShapes(self):
"""
Get properties constrained by SHACL shapes.
Returns:
list: Properties with SHACL shape constraints
"""Analyze SKOS concept schemes, hierarchies, and broader/narrower relationships.
def getSKOSInstances(self):
"""
Extract all SKOS concept instances.
Returns:
list: SKOS concept URIs with scheme information
"""
def getSKOSDirectSupers(self, aURI):
"""
Get broader concepts (immediate parents).
Parameters:
- aURI (str): SKOS concept URI
Returns:
list: Direct broader concept URIs
"""
def getSKOSDirectSubs(self, aURI):
"""
Get narrower concepts (immediate children).
Parameters:
- aURI (str): SKOS concept URI
Returns:
list: Direct narrower concept URIs
"""Extract SHACL shape definitions and constraint specifications.
def getShapes(self):
"""
Extract all SHACL shape definitions.
Returns:
list: SHACL shape URIs with constraint metadata
"""Extract detailed metadata and triple information for specific entities.
def entityTriples(self, aURI):
"""
Get all RDF triples for specified entity.
Parameters:
- aURI (str): Entity URI
Returns:
list: RDF triples as (subject, predicate, object) tuples
"""import ontospy
from ontospy.core.sparql_helper import SparqlHelper
# Load ontology
g = ontospy.Ontospy("ontology.owl", build_all=True)
# Create SPARQL helper
helper = SparqlHelper(g.rdflib_graph)
# Analyze class hierarchy depth
classes = helper.getAllClasses()
for class_uri in classes:
supers = helper.getClassAllSupers(class_uri)
subs = helper.getClassAllSubs(class_uri)
instances = helper.getClassInstancesCount(class_uri)
print(f"Class: {class_uri}")
print(f" Ancestors: {len(supers)}")
print(f" Descendants: {len(subs)}")
print(f" Instances: {instances}")
# Property usage analysis
properties = helper.getAllProperties()
for prop_uri in properties:
# Custom SPARQL to find domain/range usage
domain_query = f"""
SELECT DISTINCT ?domain WHERE {{
<{prop_uri}> rdfs:domain ?domain
}}
"""
domains = g.query(domain_query)
range_query = f"""
SELECT DISTINCT ?range WHERE {{
<{prop_uri}> rdfs:range ?range
}}
"""
ranges = g.query(range_query)
print(f"Property: {prop_uri}")
print(f" Domains: {[str(row.domain) for row in domains]}")
print(f" Ranges: {[str(row.range) for row in ranges]}")import ontospy
# Connect to remote SPARQL endpoint
g = ontospy.Ontospy(
sparql_endpoint="http://dbpedia.org/sparql",
build_all=False # Don't build locally, query remotely
)
# Query remote endpoint
results = g.query("""
PREFIX dbo: <http://dbpedia.org/ontology/>
SELECT ?person ?name ?birthPlace WHERE {
?person a dbo:Person ;
foaf:name ?name ;
dbo:birthPlace ?birthPlace .
FILTER(LANG(?name) = "en")
}
LIMIT 10
""")
for row in results:
print(f"Person: {row.name}, Born: {row.birthPlace}")
# Use SPARQL helper with endpoint
helper = SparqlHelper(g.rdflib_graph, sparql_endpoint=True)
# Note: Some helper methods may not work with remote endpointsdef find_classes_with_instances(g, min_instances=1):
"""Find classes that have at least N instances."""
query = f"""
SELECT ?class (COUNT(?instance) as ?count) WHERE {{
?class a rdfs:Class .
?instance a ?class
}}
GROUP BY ?class
HAVING(COUNT(?instance) >= {min_instances})
ORDER BY DESC(?count)
"""
return g.query(query)
def analyze_property_chains(g):
"""Find potential property chain patterns."""
query = """
SELECT ?prop1 ?prop2 ?common WHERE {
?x ?prop1 ?common .
?common ?prop2 ?y .
?prop1 a rdf:Property .
?prop2 a rdf:Property .
FILTER(?prop1 != ?prop2)
}
GROUP BY ?prop1 ?prop2 ?common
"""
return g.query(query)
def find_orphaned_classes(g):
"""Find classes with no superclasses or subclasses."""
query = """
SELECT DISTINCT ?class WHERE {
?class a rdfs:Class .
FILTER NOT EXISTS { ?class rdfs:subClassOf ?super }
FILTER NOT EXISTS { ?sub rdfs:subClassOf ?class }
}
"""
return g.query(query)
# Usage
g = ontospy.Ontospy("ontology.owl", build_all=True)
popular_classes = find_classes_with_instances(g, min_instances=10)
for row in popular_classes:
print(f"Class {row.class} has {row.count} instances")
orphaned = find_orphaned_classes(g)
print(f"Found {len(list(orphaned))} orphaned classes")# Use LIMIT for large result sets
results = g.query("""
SELECT ?s ?p ?o WHERE {
?s ?p ?o
}
LIMIT 1000
""")
# Use COUNT for statistics rather than retrieving all results
count_query = g.query("""
SELECT (COUNT(*) as ?total) WHERE {
?s a rdfs:Class
}
""")
# Use OPTIONAL for optional properties
results = g.query("""
SELECT ?class ?label ?comment WHERE {
?class a rdfs:Class .
OPTIONAL { ?class rdfs:label ?label }
OPTIONAL { ?class rdfs:comment ?comment }
}
""")# Template for hierarchy analysis
HIERARCHY_TEMPLATE = """
SELECT ?entity ?parent WHERE {{
?entity rdfs:subClassOf* ?parent .
?entity a {entity_type} .
?parent a {entity_type}
}}
"""
# Template for property analysis
PROPERTY_USAGE_TEMPLATE = """
SELECT ?prop (COUNT(?usage) as ?count) WHERE {{
?s ?prop ?o .
?prop a {property_type}
}}
GROUP BY ?prop
ORDER BY DESC(?count)
"""
# Usage
class_hierarchy = g.query(
HIERARCHY_TEMPLATE.format(entity_type="rdfs:Class")
)
object_prop_usage = g.query(
PROPERTY_USAGE_TEMPLATE.format(property_type="owl:ObjectProperty")
)Install with Tessl CLI
npx tessl i tessl/pypi-ontospy