diff --git a/.gitignore b/.gitignore index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b0a5122553a10c652ad2318a3e9e2df03e245638 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +env/* diff --git a/examples/compare_ontologies.py b/examples/compare_ontologies.py new file mode 100644 index 0000000000000000000000000000000000000000..fe37db47d10c9fbfd96827388506c0ebcea4b283 --- /dev/null +++ b/examples/compare_ontologies.py @@ -0,0 +1,85 @@ +#!/usr/bin/python3.10 +# -*-coding:Utf-8 -* + +#============================================================================== +# ontoScorer: Script to compare two ontologies and calculate metrics +#------------------------------------------------------------------------------ +# This script loads two OWL ontologies from local files, extracts classes from +# these ontologies and compares them. It then calculates precision, recall, and +# F1 score, which are commonly used metrics in information retrieval to assess +# the quality of a retrieval system. The paths to the ontology files are +# specified directly in the script. +#============================================================================== + +from rdflib import Graph, OWL +from rdflib.namespace import split_uri +from sklearn.metrics import precision_score, recall_score, f1_score + +# Define the path to the data folder +DATA_FOLDER_PATH = "data" + +# Define paths to the ontology files +REFERENCE_ONTOLOGY_PATH = f"{DATA_FOLDER_PATH}/reference_ontology.ttl" +GENERATED_ONTOLOGY_PATH = f"{DATA_FOLDER_PATH}/generated_ontology.ttl" + + +#============================================================================== +# Methods to manipulate ontologies and calculate the metrics +#============================================================================== + +def load_ontology(path): + g = Graph() + g.parse(path, format="ttl") + return g + + +def get_classes(ontology, ontology_path): + classes = set() + triplets_count = 0 + for s, p, o in ontology.triples((None, None, None)): + triplets_count += 1 + if o == OWL.Class: + _, class_name = split_uri(s) + classes.add(class_name) + print(f"Ontology analyzed: {ontology_path}") + print(f"Number of classes found: {len(classes)}") + print(f"Number of triplets analyzed: {triplets_count}") + return classes + + +def calculate_metrics(reference_classes, generated_classes): + all_classes = reference_classes.union(generated_classes) + y_true = [1 if cls in reference_classes else 0 for cls in all_classes] + y_pred = [1 if cls in generated_classes else 0 for cls in all_classes] + + precision = precision_score(y_true, y_pred) + recall = recall_score(y_true, y_pred) + f1 = f1_score(y_true, y_pred) + + return precision, recall, f1 + + +#============================================================================== +# Main Method +#============================================================================== + +def main(): + # Load ontologies + ref_ontology = load_ontology(REFERENCE_ONTOLOGY_PATH) + gen_ontology = load_ontology(GENERATED_ONTOLOGY_PATH) + + # Extract classes + ref_classes = get_classes(ref_ontology, REFERENCE_ONTOLOGY_PATH) + gen_classes = get_classes(gen_ontology, GENERATED_ONTOLOGY_PATH) + + # Calculate metrics + precision, recall, f1 = calculate_metrics(ref_classes, gen_classes) + + # Print results + print(f"Precision: {precision}") + print(f"Recall: {recall}") + print(f"F1 Score: {f1}") + +if __name__ == "__main__": + main() + diff --git a/examples/data/generated_ontology.ttl b/examples/data/generated_ontology.ttl new file mode 100644 index 0000000000000000000000000000000000000000..2b5ee473b9aaafcdab815b06788bd4a9aa435474 --- /dev/null +++ b/examples/data/generated_ontology.ttl @@ -0,0 +1,104 @@ +@prefix ns1: <https://tenet.tetras-libre.fr/base-ontology#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + +<https://tenet.tetras-libre.fr/extract-result#SolarSystem> a owl:Individual, + <https://tenet.tetras-libre.fr/extract-result#system>, + <https://tenet.tetras-libre.fr/extract-result#system-hasPart-object>, + <https://tenet.tetras-libre.fr/extract-result#system-hasPart-sun> ; + rdfs:label "SolarSystem" ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#direct> a owl:ObjectProperty ; + rdfs:label "direct" ; + rdfs:subPropertyOf ns1:Out_ObjectProperty ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#gravitation-bind-system> a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty <https://tenet.tetras-libre.fr/extract-result#bind> ; + owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#system> ], + <https://tenet.tetras-libre.fr/extract-result#gravitation> ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#hasManner> a owl:ObjectProperty ; + rdfs:label "hasManner" ; + rdfs:subPropertyOf ns1:Out_ObjectProperty ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#not-direct> a owl:ObjectProperty ; + rdfs:subPropertyOf ns1:Out_ObjectProperty ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#object-orbit-hasManner-direct-sun> a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty <https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-direct> ; + owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#sun> ], + <https://tenet.tetras-libre.fr/extract-result#object> ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#object-orbit-hasManner-not-direct-sun> a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty <https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-not-direct> ; + owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#sun> ], + <https://tenet.tetras-libre.fr/extract-result#object> ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#bind> a owl:ObjectProperty ; + rdfs:label "bind" ; + rdfs:subPropertyOf ns1:Out_ObjectProperty ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#gravitation> a owl:Class ; + rdfs:label "gravitation" ; + rdfs:subClassOf ns1:Entity ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-direct> a owl:ObjectProperty ; + rdfs:subPropertyOf <https://tenet.tetras-libre.fr/extract-result#orbit> ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#orbit-hasManner-not-direct> a owl:ObjectProperty ; + rdfs:subPropertyOf <https://tenet.tetras-libre.fr/extract-result#orbit> ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#system-hasPart-object> a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty <https://tenet.tetras-libre.fr/extract-result#hasPart> ; + owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#object> ], + <https://tenet.tetras-libre.fr/extract-result#system> ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#system-hasPart-sun> a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty <https://tenet.tetras-libre.fr/extract-result#hasPart> ; + owl:someValuesFrom <https://tenet.tetras-libre.fr/extract-result#sun> ], + <https://tenet.tetras-libre.fr/extract-result#system> ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#hasPart> a owl:ObjectProperty ; + rdfs:label "hasPart" ; + rdfs:subPropertyOf ns1:Out_ObjectProperty ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#orbit> a owl:ObjectProperty ; + rdfs:label "orbit" ; + rdfs:subPropertyOf ns1:Out_ObjectProperty ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#object> a owl:Class ; + rdfs:label "object" ; + rdfs:subClassOf ns1:Entity ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#sun> a owl:Class ; + rdfs:label "sun" ; + rdfs:subClassOf ns1:Entity ; + ns1:fromStructure "unknown" . + +<https://tenet.tetras-libre.fr/extract-result#system> a owl:Class ; + rdfs:label "system" ; + rdfs:subClassOf ns1:Entity, + ns1:Undetermined_Thing ; + ns1:fromStructure "unknown" . + diff --git a/examples/data/reference_ontology.ttl b/examples/data/reference_ontology.ttl new file mode 100644 index 0000000000000000000000000000000000000000..2b9713297e6616b251f740fc10991dc2f265c5c4 --- /dev/null +++ b/examples/data/reference_ontology.ttl @@ -0,0 +1,109 @@ +@prefix base: <https://reference.tetras-libre.fr/base-ontology#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix result: <https://reference.tetras-libre.fr/expected-result#> . + +result:SolarSystem a owl:Individual, + result:system, + result:system-isBindBy-gravitation, + result:system-hasPart-object-orbit-sun, + result:system-hasPart-sun ; + rdfs:label "SolarSystem" . + +result:direct a owl:ObjectProperty ; + rdfs:label "direct" ; + rdfs:subPropertyOf base:Out_ObjectProperty . + +result:gravitation-bind-system a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:bind ; + owl:someValuesFrom result:system ], + result:gravitation . + +result:hasManner a owl:ObjectProperty ; + rdfs:label "hasManner" ; + rdfs:subPropertyOf base:Out_ObjectProperty . + +result:not-direct a owl:ObjectProperty ; + rdfs:subPropertyOf base:Out_ObjectProperty . + +result:object-orbit-sun a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:orbit ; + owl:someValuesFrom result:sun ], + result:object . + +result:object-orbit-hasManner-direct-sun a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:orbit-hasManner-direct ; + owl:someValuesFrom result:sun ], + result:object-orbit-sun . + +result:object-orbit-hasManner-not-direct-sun a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:orbit-hasManner-not-direct ; + owl:someValuesFrom result:sun ], + result:object-orbit-sun . + +result:gravitation a owl:Class ; + rdfs:label "gravitation" ; + rdfs:subClassOf base:Entity . + +result:system-isBindBy-gravitation a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:isBindBy ; + owl:someValuesFrom result:gravitation ], + result:system . + +result:system-hasPart-object a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:hasPart ; + owl:someValuesFrom result:object ], + result:system . + +result:system-hasPart-object-orbit-sun a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:hasPart ; + owl:someValuesFrom result:object-orbit-sun ], + result:system-hasPart-object . + +result:system-hasPart-sun a owl:Class ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty result:hasPart ; + owl:someValuesFrom result:sun ], + result:system . + +result:bind a owl:ObjectProperty ; + rdfs:label "bind" ; + rdfs:subPropertyOf base:Out_ObjectProperty . + +result:isBindBy owl:inverseOf result:bind ; + rdfs:label "isBindBy" ; + rdfs:subPropertyOf base:Out_ObjectProperty . + +result:orbit a owl:ObjectProperty ; + rdfs:label "orbit" ; + rdfs:subPropertyOf base:Out_ObjectProperty . + +result:orbit-hasManner-direct a owl:ObjectProperty ; + rdfs:subPropertyOf result:orbit . + +result:orbit-hasManner-not-direct a owl:ObjectProperty ; + rdfs:subPropertyOf result:orbit . + +result:hasPart a owl:ObjectProperty ; + rdfs:label "hasPart" ; + rdfs:subPropertyOf base:Out_ObjectProperty . + +result:object a owl:Class ; + rdfs:label "object" ; + rdfs:subClassOf base:Entity . + +result:system a owl:Class ; + rdfs:label "system" ; + rdfs:subClassOf base:Entity. + +result:sun a owl:Class ; + rdfs:label "sun" ; + rdfs:subClassOf base:Entity . + diff --git a/examples/example.py b/examples/example.py deleted file mode 100644 index 4415d78eaa2ad835966f1b350fdefbdf3e9d9d61..0000000000000000000000000000000000000000 --- a/examples/example.py +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/python3.10 -# -*-coding:Utf-8 -* - -#============================================================================== -# ontoScorer: [brief description of the module] -#------------------------------------------------------------------------------ -# Detailed module description, if needed -#============================================================================== - -# TODO diff --git a/requirements.txt b/requirements.txt index f4555155474931bfd1194db3acf9f00b37783cbb..961774170971eaec5a8f937e9b5fa8127097285a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ rdflib +scikit-learn