diff --git a/ontoScorer/metrics.py b/ontoScorer/metrics.py index feedd3327057aa10299e37b6698be1c4cf9f1f2f..e6e06c5e28eb368645b06f58302c8431e407000f 100644 --- a/ontoScorer/metrics.py +++ b/ontoScorer/metrics.py @@ -43,8 +43,8 @@ class Metrics: methods = [ ("class", "get_classes"), ("object_property", "get_object_properties"), - ("data_property", "get_data_properties"), - ("restriction", "get_restrictions"), + #("data_property", "get_data_properties"), + #("restriction", "get_restrictions"), ("individual", "get_individuals"), #("annotation", "get_annotations") ] diff --git a/ontoScorer/ontology.py b/ontoScorer/ontology.py index cb2d501cd78090b846f8c42725596f5994bd4388..c5769c174058eff8c50e82efb6626db130b6a255 100644 --- a/ontoScorer/ontology.py +++ b/ontoScorer/ontology.py @@ -13,47 +13,8 @@ from rdflib import Graph, RDF, RDFS, OWL from rdflib import URIRef, BNode from rdflib.namespace import split_uri - -#============================================================================== -# Classes: Element, NamedElement and BlankElement -#============================================================================== - -class Element: - def __init__(self, reference, graph): - self.reference = reference - self.graph = graph - - def properties(self): - """Retrieve properties associated with the element.""" - return list(self.graph.predicate_objects(subject=self.reference)) - - def name(self): - raise NotImplementedError("The method name() must be implemented by subclasses.") - -class NamedElement(Element): - def __init__(self, uri, graph): - super().__init__(uri, graph) - self.uri = uri - - def __str__(self): - return str(self.uri) - - def name(self): - _, element_name = split_uri(self.uri) - return element_name - -class BlankElement(Element): - def __init__(self, bnode, graph): - super().__init__(bnode, graph) - self.id = str(bnode) - - def __str__(self): - return f"BNode: {self.id}" - - def name(self): - return self.id - - +from ontology_metadata import Metadata +from ontology_element import Element, NamedElement, BlankElement #============================================================================== # Class: Ontology @@ -81,7 +42,7 @@ class Ontology: g = Graph() g.parse(path, format="ttl") return g - + def _get_elements_of_type(self, rdf_type): """Extract all elements of a specific RDF type from the ontology.""" elements = [] @@ -94,7 +55,30 @@ class Ontology: #-------------------------------------------------------------------------- - # Extracting Method(s) + # Metadata and Annotation Extraction + #-------------------------------------------------------------------------- + + def extract_metadata(self): + """Extract metadata from the ontology and return a Metadata object.""" + version_info = self._get_version_info() + namespaces = list(self.graph.namespaces()) + return Metadata(version_info, namespaces) + + def _get_version_info(self): + pass # TODO + return -1 + + + def get_annotations(self): + """Extract all annotation comments from the ontology.""" + annotations = set() + for _, _, o in self.graph.triples((None, RDFS.label, None)): + annotations.add(str(o)) + return annotations + + + #-------------------------------------------------------------------------- + # Element Extraction #-------------------------------------------------------------------------- def get_classes(self): @@ -108,10 +92,6 @@ class Ontology: def get_data_properties(self): """Extract all data properties from the ontology.""" return self._get_elements_of_type(OWL.DatatypeProperty) - - def get_restrictions(self): - """Extract all restrictons from the ontology.""" - return self._get_elements_of_type(OWL.Restriction) def get_individuals(self) -> list: """Extract all individuals from the ontology, including elements explicitly typed as owl:Individual, @@ -128,14 +108,22 @@ class Ontology: for s, _, o in self.graph.triples((None, RDF.type, cls))] return list(set(individuals)) # Ensuring uniqueness + + #-------------------------------------------------------------------------- + # Taxonomic Relation Extraction (Hierarchical Structure) + #-------------------------------------------------------------------------- + + def get_taxonomic_relations(self): + return [] - def get_annotations(self): - """Extract all annotation comments from the ontology.""" - annotations = set() - for _, _, o in self.graph.triples((None, RDFS.label, None)): - annotations.add(str(o)) - return annotations + #-------------------------------------------------------------------------- + # Non-Taxonomic Relation Extraction + #-------------------------------------------------------------------------- + + def get_restrictions(self): + """Extract all restrictons from the ontology.""" + return self._get_elements_of_type(OWL.Restriction) #-------------------------------------------------------------------------- diff --git a/ontoScorer/ontology_element.py b/ontoScorer/ontology_element.py new file mode 100644 index 0000000000000000000000000000000000000000..8e5e80ffff47818529877305256724cf402f39df --- /dev/null +++ b/ontoScorer/ontology_element.py @@ -0,0 +1,48 @@ +#!/usr/bin/python3.10 +# -*-coding:Utf-8 -* + +#============================================================================== +# Ontology Elements +#------------------------------------------------------------------------------ +# Represents various elements (Classes, Object Properties, Data Properties, +# Individuals) within an ontology. +#============================================================================== + +from rdflib import URIRef, BNode +from rdflib.namespace import split_uri + +class Element: + def __init__(self, reference, graph): + self.reference = reference + self.graph = graph + + def properties(self): + """Retrieve properties associated with the element.""" + return list(self.graph.predicate_objects(subject=self.reference)) + + def name(self): + raise NotImplementedError("The method name() must be implemented by subclasses.") + +class NamedElement(Element): + def __init__(self, uri, graph): + super().__init__(uri, graph) + self.uri = uri + + def __str__(self): + return str(self.uri) + + def name(self): + _, element_name = split_uri(self.uri) + return element_name + +class BlankElement(Element): + def __init__(self, bnode, graph): + super().__init__(bnode, graph) + self.id = str(bnode) + + def __str__(self): + return f"BNode: {self.id}" + + def name(self): + return self.id + diff --git a/ontoScorer/ontology_metadata.py b/ontoScorer/ontology_metadata.py new file mode 100644 index 0000000000000000000000000000000000000000..2999366510e0c14f2c653ef78af053ea4baf79fa --- /dev/null +++ b/ontoScorer/ontology_metadata.py @@ -0,0 +1,18 @@ +#!/usr/bin/python3.10 +# -*-coding:Utf-8 -* + +#============================================================================== +# Metadata Container +#------------------------------------------------------------------------------ +# Holds metadata (Imports, Versions, Namespaces) from RDF/OWL ontologies. +#============================================================================== + +class Metadata: + + def __init__(self, version_info, namespaces): + """Initialize with metadata information.""" + self.version_info = version_info + self.namespaces = namespaces + + # TODO: add methods to print or manage metadata, if needed. + diff --git a/tests/test_ontology.py b/tests/test_ontology.py index da89d127abbd6f1dc7701f9fd0922c030e497281..948d4142345022751698bbeed7829aef15df53ff 100644 --- a/tests/test_ontology.py +++ b/tests/test_ontology.py @@ -57,9 +57,10 @@ class TestOntology(unittest.TestCase): self.assertIn("orbit", object_properties_names) def test_get_data_properties(self): - data_properties_names = {dp.name() for dp in self.onto1.get_data_properties()} - - self.assertEqual(len(data_properties_names), 0) + data_properties_names_1 = {dp.name() for dp in self.onto1.get_data_properties()} + data_properties_names_2 = {dp.name() for dp in self.onto2.get_data_properties()} + self.assertEqual(len(data_properties_names_1), 0) + self.assertEqual(len(data_properties_names_2), 0) def test_get_restrictions(self): restrictions = self.onto1.get_restrictions()