From 1b39f6239a7311bdb9938acd2afa243df9047c8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Lamercerie?= <aurelien.lamercerie@tetras-libre.fr> Date: Fri, 4 Aug 2023 12:50:07 +0200 Subject: [PATCH] Update library and add a main script --- README.md | 34 +++--- data/generated_ontology.ttl | 104 +++++++++++++++++ data/reference_ontology.ttl | 109 ++++++++++++++++++ main.py | 30 +++++ ontoScorer/__init__.py | 15 +-- .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 607 bytes .../__pycache__/metrics.cpython-311.pyc | Bin 0 -> 1704 bytes .../__pycache__/ontology.cpython-311.pyc | Bin 0 -> 1930 bytes ontoScorer/__pycache__/report.cpython-311.pyc | Bin 0 -> 2283 bytes ontoScorer/__pycache__/scorer.cpython-311.pyc | Bin 0 -> 1726 bytes ontoScorer/metrics.py | 20 +++- ontoScorer/ontology.py | 27 ++++- ontoScorer/report.py | 34 +++++- ontoScorer/scorer.py | 26 ++++- tests/__init__.py | 10 -- 15 files changed, 367 insertions(+), 42 deletions(-) create mode 100644 data/generated_ontology.ttl create mode 100644 data/reference_ontology.ttl create mode 100644 main.py create mode 100644 ontoScorer/__pycache__/__init__.cpython-311.pyc create mode 100644 ontoScorer/__pycache__/metrics.cpython-311.pyc create mode 100644 ontoScorer/__pycache__/ontology.cpython-311.pyc create mode 100644 ontoScorer/__pycache__/report.cpython-311.pyc create mode 100644 ontoScorer/__pycache__/scorer.cpython-311.pyc diff --git a/README.md b/README.md index d295f3e..8e95455 100644 --- a/README.md +++ b/README.md @@ -21,27 +21,27 @@ All dependencies are listed in **requirements.txt**. We recommend creating a virtual environment before proceeding: -1. Create a virtual environment: -> python3 -m venv env +1. Create a virtual environment: `python3 -m venv env` -2. Activate the virtual environment: -> source env/bin/activate +2. Activate the virtual environment: `source env/bin/activate` ## Usage Here's an example of how to use ontoScorer: -> from ontoScorer import OntoScorer -> -> # Initialize the scorer -> scorer = OntoScorer("path/to/reference_ontology.ttl", "path/to/generated_ontology.ttl") -> -> # Compare the ontologies -> scorer.compare() -> -> # Print the scores -> scorer.print_scores() -> -> # Generate a report -> scorer.generate_report("path/to/report.txt") +```python +from ontoScorer import OntoScorer + +# Initialize the scorer +scorer = OntoScorer("path/to/reference_ontology.ttl", "path/to/generated_ontology.ttl") + +# Compare the ontologies +scorer.compare() + +# Print the scores +scorer.print_scores() + +# Generate a report +scorer.generate_report("path/to/report.txt") +``` diff --git a/data/generated_ontology.ttl b/data/generated_ontology.ttl new file mode 100644 index 0000000..2b5ee47 --- /dev/null +++ b/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/data/reference_ontology.ttl b/data/reference_ontology.ttl new file mode 100644 index 0000000..2b97132 --- /dev/null +++ b/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/main.py b/main.py new file mode 100644 index 0000000..fe59030 --- /dev/null +++ b/main.py @@ -0,0 +1,30 @@ +#!/usr/bin/python3.10 +# -*-coding:Utf-8 -* + +#============================================================================== +# ontoScorer: [brief description of the module] +#------------------------------------------------------------------------------ +# Detailed module description, if needed +#============================================================================== + +from ontoScorer.scorer import OntoScorer + +def main(): + # 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" + + # Initialize the scorer + scorer = OntoScorer(REFERENCE_ONTOLOGY_PATH, GENERATED_ONTOLOGY_PATH) + + # Compare the ontologies + scorer.compare() + + # Generate a report + scorer.generate_report() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/ontoScorer/__init__.py b/ontoScorer/__init__.py index 4415d78..162f653 100644 --- a/ontoScorer/__init__.py +++ b/ontoScorer/__init__.py @@ -1,10 +1,5 @@ -#!/usr/bin/python3.10 -# -*-coding:Utf-8 -* - -#============================================================================== -# ontoScorer: [brief description of the module] -#------------------------------------------------------------------------------ -# Detailed module description, if needed -#============================================================================== - -# TODO +# -- Update System Path +import os, sys +LIB_PATH = os.path.dirname(os.path.abspath(__file__)) + '/' +os.chdir(LIB_PATH) +sys.path.insert(0, os.path.abspath(LIB_PATH)) diff --git a/ontoScorer/__pycache__/__init__.cpython-311.pyc b/ontoScorer/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15c9d4b5e58309a39ad2614703ebff6ad3759740 GIT binary patch literal 607 zcmZ3^%ge>Uz`*eQ%$bxW3=9m9K^z!ngEBs|F)}brXGmd4Va#EOg3ydnjHwJ+Oi&dJ z3z%UnWEw>U3$hH1oyxk5k%3_~BaDyAOJS;FU|@)1V`4~U$YO`7No7M-#mJD#h~yFu zm^x%S1!Mxkwb<Q)X6`a328PveJ&X(~jKK_=%r8O4`u$?m*W|p#lwW*{xwx|U7E3{5 zNyaVql+2>M#N5<d?1@RmU=fb^__WNN)cE*Y96p{-@d1t@9=BMNGg2~(Zn0(N6{i-J ztYr8MGVqs!enx(7s(wylZfagurha&SQFd`bVsff}NNPz@VzGXHUP*p&a(+>25ttba zVaCU2=4F<|$LkeT{^GF7%}*)KNwq5yU|?VXg=ldF0|UbcW=2NF2Ml}-DDVb1Z;yGu zeV6?VqdDgD?PuAqu(&8~az)zYBDd)kZqpsi7rCt)IBqa-G%&SrbVyue5W2!3bb&$W u1_N^oM>~HL{{+SfMpMkE+fTAzU~y4c=Zdh-MF!m~47wL!sECh&fdK$ee}YB; literal 0 HcmV?d00001 diff --git a/ontoScorer/__pycache__/metrics.cpython-311.pyc b/ontoScorer/__pycache__/metrics.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3d7b0f5b4273d827168b62f4a05c4bc64426e93 GIT binary patch literal 1704 zcmZ3^%ge>Uz`zi8@l47!W(J1GAPx+(KpCG+7#J9)Go&!2Fy=7iGDb1xGDR`vGDk5p zGB7c?Go&!JFr+XqV`5-f%>>oK5XF+h63n2<`Vu6d$$X2ypeQvtvp6$9FTOZAzbN$< zPf==eVonZ}$B||TVI_mq!!RS1@mUINe=0*1V+unQQwn1XLliT})+m+~=3oX*mRsz; zsU=03$;HVqEg+pB$1pQ6Fnl%uYfoXUVTcEbgE5!~R}JQY)I;PLf*CZK{E9#Vn#{L2 z;cmah266Q*rZhuM##=1KsX1xIAVU;>+3RQI=celCB<7~(Wo7Dz=NDxc7bGU9>W8G3 z6eSkx=jWB=gMD5EW(I=-p-4X$;%vQw%3B=q@tJv<CGqi90#MKB!9;i&7#NDB85kHE z7;Z>Pb+GjC-4GM+VCmt$Atc<v(!<`t-ogGE<nm;YcR>sg2E`tT|M?XI14BDwJJWQA zPR0cw84TRXw2YB~VKvAnV7Xf64#qUb6vh^g8fF)UWef}qtHI(RqL!tDDUC6O39B4y z3CKo}G6n{Q8kQPX)KpQ!5DyAduzU$Sm;w`6Rf60PmM!51Q(ywCN;a?*0|P?}DB_s? zP*MTN7-3K<P+(wSn94YvA)TRyA(pF_v4*jesf?kBDTN`AF@<p=QxA7A!%C)?pg;h} z{7ME*=37j92Dg}#bBb>X7Nw@87NzDTr^YAeBo-H^78irOs-VzN1d5(tTsAqG#U;u4 zxdnDrs;~%5PRvOz%}Fdt)w9XTPfpA!w$no>69G9&gMoqJM+3tJK|cuEVLYMuf}H*Z zaS)oII6-kkAVlJVpkEO`0|Nv3ek&4UU|=W$*{aE0Bno1SF)%RP5=>9cOD#$)Nln4( zu_6fu1_mO11U6I>WHQL5n(Vh&OY<`G^NK(LRm2Gr2Sr8^sK6;=1#v+UtI1Zx17eGV z2v8!w#SJPKpn-ggtunr(s5BKs7ZjzY6ocYgAt6CQK>-}@w>aTpTqTGR>>wW(H-dur zM+3tRG4<<Wx|hUsFX-7{6mz&D=Fq`?0~YQV1pN+ZUl8=WDCl=Z(656Hr^Hi9jTK@W z#4bu&T#>W@WyQN<N(;<Zm|YYzx*}!-%9MA7q-K~cFuN$Ebwx-EmOa67=cmaE%I0~A zxvBB-x47ctbMsS5b3kmK`1r!o#2koB5g#ZhK*<#xTVSnV&lZ8Q4443gSg{efL}*}u zzz<B!tRf#6-~<;ttM&&5OafvY$Rv<+_=~f1QWJ~v^q?gXB(A{G1dbt)Iy6`O;;@0Z z+pb8Jfq?;(Uy36b7#Kb<Gcq!M5Mf|+VZ6ZLj0=5W;bqkRz<^171c`kC5ooet2Lk}{ Cx{7uH literal 0 HcmV?d00001 diff --git a/ontoScorer/__pycache__/ontology.cpython-311.pyc b/ontoScorer/__pycache__/ontology.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aafe00e11d0aad998e8c002a193da51608e8d62d GIT binary patch literal 1930 zcmZ3^%ge>Uz`$_s!kLsR76yjLAPx+(KpCHH7#J9)Go&!2Fy=7iGDb1xGDR^lg7{21 z%(*O4EQ}0H4DJjm%q<KlEX$Y}7*;bubuvV;rmzMxXtKQo31~9iVs$S{EXcUU>>uu< z$#{#ixF9F9B)+sLGZ`cg!;DbIXEm_BsSHt!DGX6eDU2-)QOqe!EeugCAiJViQ&?IU zqSzod+~V-hE6LBvPp?dd+s?qizzoHotH5T}FxD`{Lyc!(s9{(DvkNW;V$?7$V`N}h z4VSB7h=-e5!>|BkCP*0yUdF({uo^B>!w?S(J%$v9V1|{9ewwVeSPBwLGH&ta<R_-Y z=R;k4i!~h_B;4t#CGp8QiN(dK#kbg@3{9q6EXAogX}5S`%Hu&s6oXu&pzzB<KO;Xk zRX-;&H#ILSQ$IYvD7&~IF*#K~B(<a{u~;9ZsW>^mD76U83`Q_P;iOkkd5a@HJ~J<~ zBtE`M5EguTFd;q$28Lo&1_p)(h8rS^9V|VZH$)|`i>hA|RbRn-QPk{;s96U~57!NG z>FeU^m&DaCifdjG*X&^F;pyP%;Q0&+3zVn;1qdkUJ_mrKq68ki3=F7&SIbnxgeziF z7}qeNCNV~a8m3?dO=iDa%q1l`nvA#D((;RP6H7Fiia@sAVl7B4Do)j8F5+ikU?>8m z_FIhU#ULpK1%)C(kRUe$14ES<JOEJQM;H_epoG}KaF<80)4j*NgYgCjXFq!v`vjI5 zp&jfOIh3z(C|}@EzQHfh!BGTKpN!-+2DrB$5b`!-3S%u(4MP@O_X1EngTfI7r!b+W zP8Wt)rx<1ihFa!YmRi;trWEEXUIvC*rW)1~HiX73kUPNKY_O?C>Lnm=gGCq^YM4>Y zjA3G6sAa2VuVGw(WCm0*0|P@1JF0p{h92h{#$X0b7QZ5p@tVwjets`O9?@jK#ax_P zQpCf+z;KJbq$sl>C$+c;<d|Em&Y<L8#0rvOPE1MB<bcExDB<1WgD5R2j!(`n%`3UZ zSbU4I;1*;4Eynm;T;S{xpO=`MTFk+~z@PvHkl5q}#ij^6Hj(m`1Sl?xz$yB!kmy9! zDXJapHzcJx_-=?xPpP^tu6apZ^MaPmMRD6J;<g_cSU5GnM5lX)V@Kfx#Tz_QGZHWI z$anbN;1`(cJjJuCuA}a*g60avg*;1mCh|^ToM3fBKzus)B<>kr7X{R>2&i8WQ2%j* zU#x=<k}g0&0}DhD8<Yw^%YoBH4MP@8hM|TL!A@feW+>uhU|`T>ECL0LCKEW2Zt>-p zWTY0sixFs%01km$T*>*l1&Kwe@g@0H!tj7V2r7ZXK?ocUH~58nYG%Y;ku|=+Z+wBn z80=0zO?FVp01Dsu_*-1@@wxdar8%kb@wa&5;|og@b09KBAR~%Esi+7P=0)lZ3=At7 zz$Sp*QN#|)Tp$7@T@1?h4Gb{&fr*(_>jMLv;9_PK1aYAR7YD2O2L?DH!pLg!fdP|% zSO&7fPm}EyTTx0{PG%A~-$Rm^07OI&<X~{o2u^JfhiQXc2g<Hs$Nu85f%wv{NRNSm z0hDx$LABBcW=2NF4<ZbVau*n6G0_bMwF{`|1B)1=$p;2Z;v-1x3y46I1$zPjzzn7q literal 0 HcmV?d00001 diff --git a/ontoScorer/__pycache__/report.cpython-311.pyc b/ontoScorer/__pycache__/report.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3ac64f032d3c2903f9d0664b49ed1fe36c6d71ac GIT binary patch literal 2283 zcmZ3^%ge>Uz`(Hl!kLt<><kQ#K^z!nfigZTFfcGoXJBG*XGmdaVMt+I#>Bv|nh7e) z5XF$f6wIK>oD35H(TpI1fq~((6j*O6Llk2QLljdAV+%tRa|%-nLljF2b1;J@%PqE` z)Pnq?l4Mq>4iE)0n;E3r4y?O|v4$ZYBo4+kOf?MgF!LE|m}?l~LFyrLEHw=AAe~@d z3PUi1CZnGw%Ppaz)U?#1)V$=>`24(*{G9ys%3DI|sd=eIi6yBi2r<Fr{M>@XqRis_ zy!fKj;?kUwTkN^1B}JLZ#hR?QSc+3~(uzP1En;I}U?^e-5gZH*48<TZ1rYdUr=O9Z zo2s9an46lHm8l<|UzA;3keHmRACg*9lvu0}vc5PuzbLf`%nXJwi@;%^S5SG2BR)Pe zFS8^*zKS0bFnTZnZjeQ)3=9kn3^$ZaI#{l7$irzxBM@KihPYe@OAk*6PY2IuPzWT$ zgNcEG0pvzd(0q1a0!3#EV=ZG1V+vCZLl#IW7-zxN&t{m*RK?4{09M0X0@4ds!N7o` z9%LR^d>JDH!)olhS!x)vU`dGqhYhS~HXzg!V*?w+rD$e=-321DaF~Ino}iuCU=>Ad zHH<0j5F7LC(aZo@2gX#h6KopTP7bJ@tTl`&oDg;mV+t3X#a+XY1&^mJPyz+(MTtos z6g8mqi>ZbeMGYu<W2gyc(B$*0Qnt0VRq%&qCk5BC#GKN^lFa-(1xUhGu(h@2suJZ2 zf@M9pS}TPrEiS*(+@#bZh5R&y<ebFf;?!b=Ops1!Hbqt|#>M3h%c{uYILyGRR+Nj& z8J@Kjg1}kZN}<X%BqLP;UJfXLGAF2PP{>FuR!B=NPc4Ewt|TKdPoX3uRRLa-z*Xy2 zx!^G-H@_&AI8%afn39;6g2QHojKs23uv~FsZmL2adXVZ>iE?ovMT{?`D6^{K;R+~9 zP0lRN%+Iq@sN&=bN=;78$+1$X;^uNQQ~(!BRtlP&;Ii%(OF?2u#x3TY)Vy2l(71w> zf1tE+i?aY`(k-?kuraro(hN13iZ~e<7;bSvO1AjolA>ZzDXpMT1gdaualir{Ud+J+ z1VP1IFeA8_6SeN(dcYxcLCkkW$rXLKEBf9S#C$J^`CjDk?cllrlE^yhe1heQNBk9! z^ouSTS6nhKh-F<6%eu&s1=Z=lLF9^|#}z~03u68k#QZOE_!FV?0~-UU@C7mbiyZnL zTz9$oI!dnat6kyOyU4A7g<F5C@`jWvX1-U<LN6MHT`>x~#2t2lJM0FJ*afM?i#&-P zUL9U{c?BkjToKf`B4}`t*YFCj;a2AzELSZ2uULd%G>N!k5^;$);sS33SWm)5o&=Dd z2OtCTF7o7cc!B*4u^sG7y9Fsra;~V^ToALnAZB-w!w%{Piv=c2Y_2GqT@bUlAZBrq z!vZR9wjg9l%#!#EVrCb_%r0`6b#Oi4m%P9sS;WJ@z~HCJ3aVxD5_41I<8N`r$LHp! zl;(igJn`{`rHMHZnIceqQzXj3z_5}5tPdP<MWC`2On{=X*a%!5H84Qn2PPI)`40?m zf=8TH>H`BN0Wl6_lAk6c*svl=P*n<Y9oUv%95xU~*%g7>51@Lb*qniZ;R7=xBjX1V VIYy}u44A}6kk}UxfhG&K4*(zdK6n5C literal 0 HcmV?d00001 diff --git a/ontoScorer/__pycache__/scorer.cpython-311.pyc b/ontoScorer/__pycache__/scorer.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15863905c230a177ffba8eb4a80f491d1fd94ecb GIT binary patch literal 1726 zcmZ3^%ge>Uz`*eQ;+YgaRtAR0APx+(KpCH17#J9)Go&!2Fy=7iGDa~ng4j$sOu5Wa z%wRTi4ofa;6e}YG6N5WL3QG$^3hOc^28Pv4P!kxU*izVn88q2nf&?@fZ*lnNmE`B- zr&nq+-eL<%Eyyn_(PX^E?weXtl$l(d3{nNdj8MjB1+Xhp8KM|d7^0X`7+V;km{XWq z7@}BGm|Ga4SW{Sn88lgMae<5uPR=h%ElOsF>IG3CHVA*N0h?0-GnavZp@wl8BLl-~ zxJV5{Je-Z9jtN5@+=nIXAWI;483O~uY6uf#Izv1xBpFf|f*Dpa`f0Kjft+$ns3<ip zwJ0?&IW;~X8X&iX(o^$NixNvxQ{ZAntPBhcx7c$bp`*!si={X<C+(IvrtbKH#FC6# z;+RH&C5l0oDkv!YveVDV&rQ|ONz6^n%gWRb&o9a@E=WvH)elK6DM~EX2RWt~9E4yd zBsBFQB6<atw>aYCGxIV_;^V7?5uvRI6Xa)LU??_bU|?uqxT~afLEGt~lJgZM=MI)D z9P*d~;&Kx!r&M;Z^zd}>bntuz1zR#a^cff!KyC)%&t>3vt6|6jDFNdJ$m+l%AfkpL z3mz*N@dYvoq=<oup@ty~9xqv-5C)6aFl52i^f7=^cQ8W{Cj$e6CR-5~C>pqu^K%Ol zi&EoD@{71Z0)h~M%;NmK_@dO}(wvea9*{U^a$-($X-;BEswQI*FDOhv&Q&N907<e# zG^JJvAq5~*Oa!FX5*&Uv6jiS%T3lCjzNF}Uz~zcd^hL#(D~d6opp?78AqNVzD;#nQ zSgt6TUEnZ>qaq;&1_qQ+WP^s}=PBS&L`l^QSs;hOd=C#h<d8rPt7R+<46ETGSIbxe z3I(ukP)=F^vI)vVP^dWqHCB+rn7s&OFgT#Wfm<ZXz`y_rPS%2=%)F9Y9I&*l$pjA6 zTWm$(;-eVkZUt!Q^1~FxLnN!DkU|+vP68C#?%>eAD=0pL<%)#<4G9?-sdqy{W)9Cs zc4i^9FAU5=Y8`A}IT$$kI@0>{yYesc$zS1<zsR9*g+t*241vSmPm>LlN%9hNQ{&@r zamB~y=BJeAfY?0o@r9*{IS`p5L6G;vL4*tg1H(!Nux4-yDFT%zV1f_iKu53x8yFz) z0~0f=;s*ve!NtUC@qqzOaIk`8F$sw2AcOrh*>7=xayh6B2A4%e(jZrWLm!lS!9@<( z`XW%d3(*NmxxYAUAbzncQet3W0HvJbd<F)F56p~=j2}c8809W7$ReW~43Za6(G3Ra a3#jM=3qPac2L?>yBS`EEh(MDCI|u-6DS9mc literal 0 HcmV?d00001 diff --git a/ontoScorer/metrics.py b/ontoScorer/metrics.py index 4415d78..e905353 100644 --- a/ontoScorer/metrics.py +++ b/ontoScorer/metrics.py @@ -4,7 +4,23 @@ #============================================================================== # ontoScorer: [brief description of the module] #------------------------------------------------------------------------------ -# Detailed module description, if needed +# Detailed module description #============================================================================== -# TODO +from sklearn.metrics import precision_score, recall_score, f1_score + +class Metrics: + def __init__(self): + self.precision = 0 + self.recall = 0 + self.f1 = 0 + + def calculate(self, 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] + + self.precision = precision_score(y_true, y_pred) + self.recall = recall_score(y_true, y_pred) + self.f1 = f1_score(y_true, y_pred) + diff --git a/ontoScorer/ontology.py b/ontoScorer/ontology.py index 4415d78..f9403cb 100644 --- a/ontoScorer/ontology.py +++ b/ontoScorer/ontology.py @@ -7,4 +7,29 @@ # Detailed module description, if needed #============================================================================== -# TODO +from rdflib import Graph, OWL +from rdflib.namespace import split_uri + +class Ontology: + def __init__(self, ontology_path): + self.path = ontology_path + self.graph = self.load_ontology(ontology_path) + self.classes = self.get_classes() + + def load_ontology(self, path): + g = Graph() + g.parse(path, format="ttl") + return g + + def get_classes(self): + classes = set() + triplets_count = 0 + for s, p, o in self.graph.triples((None, None, None)): + triplets_count += 1 + if o == OWL.Class: + _, class_name = split_uri(s) + classes.add(class_name) + return classes + + def compare_to(self, other_ontology): + return self.classes, other_ontology.classes \ No newline at end of file diff --git a/ontoScorer/report.py b/ontoScorer/report.py index 4415d78..30f7659 100644 --- a/ontoScorer/report.py +++ b/ontoScorer/report.py @@ -7,4 +7,36 @@ # Detailed module description, if needed #============================================================================== -# TODO +class Report: + def __init__(self, reference_ontology, generated_ontology, comparison_result, metrics): + self.reference_ontology = reference_ontology + self.generated_ontology = generated_ontology + self.comparison_result = comparison_result + self.metrics = metrics + + def generate(self): + report_str = "=== Ontology Evaluation Report ===\n" + + report_str += f"\nReference Ontology: {self.reference_ontology.path}" + report_str += f"\nNumber of classes in Reference Ontology: {len(self.reference_ontology.classes)}" + + report_str += f"\n\nGenerated Ontology: {self.generated_ontology.path}" + report_str += f"\nNumber of classes in Generated Ontology: {len(self.generated_ontology.classes)}" + + # Comparison of the number of classes + report_str += "\n\nComparison Result: " + if len(self.reference_ontology.classes) > len(self.generated_ontology.classes): + report_str += "The generated ontology has fewer classes than the reference ontology." + elif len(self.reference_ontology.classes) < len(self.generated_ontology.classes): + report_str += "The generated ontology has more classes than the reference ontology." + else: + report_str += "The generated ontology and the reference ontology have the same number of classes." + + report_str += "\n\nEvaluation Metrics:" + report_str += f"\nPrecision: {self.metrics.precision}" + report_str += f"\nRecall: {self.metrics.recall}" + report_str += f"\nF1 Score: {self.metrics.f1}" + + return report_str + + diff --git a/ontoScorer/scorer.py b/ontoScorer/scorer.py index 4415d78..2ed8085 100644 --- a/ontoScorer/scorer.py +++ b/ontoScorer/scorer.py @@ -7,4 +7,28 @@ # Detailed module description, if needed #============================================================================== -# TODO +from ontology import Ontology +from report import Report +from metrics import Metrics + +class OntoScorer: + def __init__(self, reference_ontology_path, generated_ontology_path): + self.reference_ontology = Ontology(reference_ontology_path) + self.generated_ontology = Ontology(generated_ontology_path) + self.metrics = Metrics() + + def compare(self): + self.comparison_result = self.reference_ontology.compare_to(self.generated_ontology) + self.metrics.calculate(*self.comparison_result) + + def generate_report(self): + report = Report(self.reference_ontology, + self.generated_ontology, + self.comparison_result, + self.metrics) + print(report.generate()) + + + # def generate_report(self, report_path): + # report = Report(self.comparison_result, self.metrics) + # report.generate(report_path) diff --git a/tests/__init__.py b/tests/__init__.py index 4415d78..e69de29 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,10 +0,0 @@ -#!/usr/bin/python3.10 -# -*-coding:Utf-8 -* - -#============================================================================== -# ontoScorer: [brief description of the module] -#------------------------------------------------------------------------------ -# Detailed module description, if needed -#============================================================================== - -# TODO -- GitLab