From b4dfdd975f859b11cf69c973a38ad58abf326b2e Mon Sep 17 00:00:00 2001 From: Imane Amraoui Date: Fri, 5 Jun 2026 13:43:02 +0100 Subject: [PATCH 1/4] Add complex analyses stats: types, top mediators, top moderators, VI/VD categorization --- stats_bdd.py | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/stats_bdd.py b/stats_bdd.py index 1b4acda..42d5bb5 100644 --- a/stats_bdd.py +++ b/stats_bdd.py @@ -31,7 +31,8 @@ def count(sparql): PREFIX dct: """ -FILTER_SIMPLES = '?c = "Simple analyses" || ?c = "simple analyses"' +FILTER_SIMPLES = '?c = "Simple analyses" || ?c = "simple analyses"' +FILTER_COMPLEXES = '?c = "Complex analyses"' print("=" * 55) print(f" STATS BDD IADAS — {datetime.now().strftime('%d/%m/%Y %H:%M')}") @@ -273,4 +274,79 @@ def count(sparql): print(f" {'Groupes article+VI+VD (sous-groupes OK)':<35} {nb_groupes_rep:>6}") print(f" {'Vrais doublons (+ direction+valeur+n=)':<35} {nb_vrais_doublons:>6} [OK]") +# --- Analyses complexes : vue d'ensemble --- +print("\n ANALYSES COMPLEXES — VUE D'ENSEMBLE") +print(" " + "-" * 40) +cx_total = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?a) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c . FILTER({FILTER_COMPLEXES}) }}") +cx_med = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?a) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasMediator ?m . FILTER({FILTER_COMPLEXES}) FILTER(?m != 'N.A.') }}") +cx_mod = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?a) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasModerator ?m . FILTER({FILTER_COMPLEXES}) FILTER(?m != 'N.A.') }}") +cx_medmod = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?a) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasMediator ?med ; iadas:hasModerator ?mod . FILTER({FILTER_COMPLEXES}) FILTER(?med != 'N.A.') FILTER(?mod != 'N.A.') }}") +print(f" {'Total analyses complexes':<35} {cx_total:>6}") +print(f" {'Avec mediateur renseigne':<35} {cx_med:>6}") +print(f" {'Avec moderateur renseigne':<35} {cx_mod:>6}") +print(f" {'Avec mediateur ET moderateur':<35} {cx_medmod:>6}") + +# --- Repartition par type d'analyse --- +print("\n TYPES D'ANALYSES COMPLEXES (top 10)") +print(" " + "-" * 40) +d_types = query(f""" +{PREFIX} +SELECT ?type (COUNT(*) AS ?n) +WHERE {{ + ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:typeOfAnalysis ?type . + FILTER({FILTER_COMPLEXES}) +}} +GROUP BY ?type ORDER BY DESC(?n) +""") +for b in d_types["results"]["bindings"][:10]: + print(f" {b['type']['value'][:35]:<35} {b['n']['value']:>6}") + +# --- Top mediateurs --- +print("\n TOP MEDIATEURS (analyses complexes)") +print(" " + "-" * 40) +d_meds = query(f""" +{PREFIX} +SELECT ?mediateur (COUNT(DISTINCT ?a) AS ?n) +WHERE {{ + ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasMediator ?mediateur . + FILTER({FILTER_COMPLEXES}) + FILTER(?mediateur != "N.A.") +}} +GROUP BY ?mediateur ORDER BY DESC(?n) +""") +for b in d_meds["results"]["bindings"][:10]: + label = b["mediateur"]["value"][:35] + print(f" {label:<35} {b['n']['value']:>6}") + +# --- Top moderateurs --- +print("\n TOP MODERATEURS (analyses complexes)") +print(" " + "-" * 40) +d_mods = query(f""" +{PREFIX} +SELECT ?moderateur (COUNT(DISTINCT ?a) AS ?n) +WHERE {{ + ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasModerator ?moderateur . + FILTER({FILTER_COMPLEXES}) + FILTER(?moderateur != "N.A.") +}} +GROUP BY ?moderateur ORDER BY DESC(?n) +""") +for b in d_mods["results"]["bindings"][:10]: + label = b["moderateur"]["value"][:35] + print(f" {label:<35} {b['n']['value']:>6}") + +# --- Categorisation VI/VD dans les complexes --- +print("\n CATEGORISATION VI/VD (analyses complexes)") +print(" " + "-" * 40) +cx_vi_total = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasIndependentVariable ?v }}") +cx_vi_cat = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasIndependentVariable ?v . ?v iadas:refersToVariable ?concept . ?concept skos:broader ?b }}") +cx_vd_total = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasDependentVariable ?v }}") +cx_vd_cat = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasDependentVariable ?v . ?v iadas:refersToVariable ?concept . ?concept skos:broader ?b }}") +pct_cx_vi = round(cx_vi_cat / cx_vi_total * 100) if cx_vi_total > 0 else 0 +pct_cx_vd = round(cx_vd_cat / cx_vd_total * 100) if cx_vd_total > 0 else 0 +print(f" {'VI total (complexes)':<35} {cx_vi_total:>6}") +print(f" {'VI avec categorie SKOS':<35} {cx_vi_cat:>6} ({pct_cx_vi}%)") +print(f" {'VD total (complexes)':<35} {cx_vd_total:>6}") +print(f" {'VD avec categorie SKOS':<35} {cx_vd_cat:>6} ({pct_cx_vd}%)") + print("\n" + "=" * 55) From f553922d1c2a6324fbaf3572dc444a0adfb76e34 Mon Sep 17 00:00:00 2001 From: Imane Amraoui Date: Fri, 5 Jun 2026 13:49:21 +0100 Subject: [PATCH 2/4] Document complex analyses VI categorization: N.A. bundles are expected, not a bug --- stats_bdd.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/stats_bdd.py b/stats_bdd.py index 42d5bb5..0cf36bb 100644 --- a/stats_bdd.py +++ b/stats_bdd.py @@ -336,16 +336,25 @@ def count(sparql): print(f" {label:<35} {b['n']['value']:>6}") # --- Categorisation VI/VD dans les complexes --- +# Note : dans les analyses complexes, une VI peut contenir plusieurs variables +# bundlees (ex: "BMI\nAge\nGender") → refersToVariable = N.A. (normal et intentionnel). +# Seules les analyses a VI unique et bien definie obtiennent un mapping ACAD. print("\n CATEGORISATION VI/VD (analyses complexes)") print(" " + "-" * 40) cx_vi_total = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasIndependentVariable ?v }}") +cx_vi_na = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasIndependentVariable ?v . ?v iadas:refersToVariable ?concept . FILTER(CONTAINS(STR(?concept),'N.A')) }}") cx_vi_cat = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasIndependentVariable ?v . ?v iadas:refersToVariable ?concept . ?concept skos:broader ?b }}") cx_vd_total = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasDependentVariable ?v }}") cx_vd_cat = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?v) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasDependentVariable ?v . ?v iadas:refersToVariable ?concept . ?concept skos:broader ?b }}") +# Analyses avec au moins une VI catégorisée (métrique pertinente pour les complexes) +cx_an_with_vi_cat = count(f"{PREFIX} SELECT (COUNT(DISTINCT ?a) AS ?n) WHERE {{ ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; iadas:hasRelation ?rel . FILTER({FILTER_COMPLEXES}) ?rel iadas:hasIndependentVariable ?v . ?v iadas:refersToVariable ?concept . ?concept skos:broader ?b }}") pct_cx_vi = round(cx_vi_cat / cx_vi_total * 100) if cx_vi_total > 0 else 0 pct_cx_vd = round(cx_vd_cat / cx_vd_total * 100) if cx_vd_total > 0 else 0 +pct_cx_an = round(cx_an_with_vi_cat / cx_total * 100) if cx_total > 0 else 0 print(f" {'VI total (complexes)':<35} {cx_vi_total:>6}") +print(f" {'VI bundles (N.A. — normal)':<35} {cx_vi_na:>6} (multi-predicteurs)") print(f" {'VI avec categorie SKOS':<35} {cx_vi_cat:>6} ({pct_cx_vi}%)") +print(f" {'Analyses avec >=1 VI categ.':<35} {cx_an_with_vi_cat:>6} ({pct_cx_an}% des complexes)") print(f" {'VD total (complexes)':<35} {cx_vd_total:>6}") print(f" {'VD avec categorie SKOS':<35} {cx_vd_cat:>6} ({pct_cx_vd}%)") From 664f358b77446ab2609163884d2505ea132241ab Mon Sep 17 00:00:00 2001 From: Imane Amraoui Date: Fri, 5 Jun 2026 13:52:02 +0100 Subject: [PATCH 3/4] Add CQs q9-mediators, q9-moderators, q9-mediation-by-category for complex analyses --- services/SPARQL-Generator/index.js | 88 ++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/services/SPARQL-Generator/index.js b/services/SPARQL-Generator/index.js index cfa630e..7cc4410 100644 --- a/services/SPARQL-Generator/index.js +++ b/services/SPARQL-Generator/index.js @@ -2328,6 +2328,92 @@ WHERE { BIND(REPLACE(STR(?sportURI), '.*/([^/]+)$', '$1') AS ?sportCategory) } ORDER BY ?vi ?vd +`; + break; + + case 'q9-mediators': + console.log(" CASE Q9-MEDIATORS DÉTECTÉ: Analyses complexes — tous les médiateurs"); + selectedCase = 'q9-mediators - Médiateurs dans les analyses complexes'; + expectedResults = '100-150 analyses avec médiateur renseigné'; + + query = `${prefixes} + +SELECT DISTINCT ?vi ?vd ?mediator ?mediatorMeasure ?typeAnalysis ?direction ?analysis +WHERE { + ?analysis a iadas:Analysis ; + iadas:complexityOfAnalysis "Complex analyses" ; + iadas:hasMediator ?mediator ; + iadas:mediatorMeasure ?mediatorMeasure ; + iadas:typeOfAnalysis ?typeAnalysis ; + iadas:hasRelation ?relation . + FILTER(?mediator != "N.A.") + + ?relation iadas:hasIndependentVariable ?variableVI ; + iadas:hasDependentVariable ?variableVD . + ?variableVI iadas:variableName ?vi . + ?variableVD iadas:variableName ?vd . + + OPTIONAL { ?analysis iadas:relationDirection ?direction } +} +ORDER BY ?mediator ?vi +`; + break; + + case 'q9-moderators': + console.log(" CASE Q9-MODERATORS DÉTECTÉ: Analyses complexes — tous les modérateurs"); + selectedCase = 'q9-moderators - Modérateurs dans les analyses complexes'; + expectedResults = '25-40 analyses avec modérateur renseigné'; + + query = `${prefixes} + +SELECT DISTINCT ?vi ?vd ?moderator ?moderatorMeasure ?typeAnalysis ?direction ?analysis +WHERE { + ?analysis a iadas:Analysis ; + iadas:complexityOfAnalysis "Complex analyses" ; + iadas:hasModerator ?moderator ; + iadas:moderatorMeasure ?moderatorMeasure ; + iadas:typeOfAnalysis ?typeAnalysis ; + iadas:hasRelation ?relation . + FILTER(?moderator != "N.A.") + + ?relation iadas:hasIndependentVariable ?variableVI ; + iadas:hasDependentVariable ?variableVD . + ?variableVI iadas:variableName ?vi . + ?variableVD iadas:variableName ?vd . + + OPTIONAL { ?analysis iadas:relationDirection ?direction } +} +ORDER BY ?moderator ?vi +`; + break; + + case 'q9-mediation-by-category': + console.log(" CASE Q9-MEDIATION-BY-CATEGORY DÉTECTÉ: Médiateurs par catégorie SKOS de VI"); + selectedCase = 'q9-mediation-by-category - Chemins de médiation par catégorie'; + expectedResults = '60-80 chemins de médiation avec catégorie VI identifiée'; + + query = `${prefixes} + +SELECT DISTINCT ?categoryVI ?vi ?mediator ?vd ?typeAnalysis ?analysis +WHERE { + ?analysis a iadas:Analysis ; + iadas:complexityOfAnalysis "Complex analyses" ; + iadas:hasMediator ?mediator ; + iadas:typeOfAnalysis ?typeAnalysis ; + iadas:hasRelation ?relation . + FILTER(?mediator != "N.A.") + + ?relation iadas:hasIndependentVariable ?variableVI ; + iadas:hasDependentVariable ?variableVD . + ?variableVI iadas:variableName ?vi ; + iadas:refersToVariable ?viConcept . + ?viConcept skos:broader+ ?top . + ?top skos:prefLabel ?categoryVI . + FILTER NOT EXISTS { ?top skos:broader ?x . FILTER(CONTAINS(STR(?x), 'ACAD-vocab')) } + + ?variableVD iadas:variableName ?vd . +} +ORDER BY ?categoryVI ?mediator `; break; @@ -2341,6 +2427,8 @@ ORDER BY ?vi ?vd console.error(" - q6-female, q6-male, q6-mixed"); console.error(" - q7-volleyball-men-21"); console.error(" - q8-individual, q8-team, q8-mixed, q8-aesthetic"); + console.error(" [Analyses complexes]"); + console.error(" - q9-mediators, q9-moderators, q9-mediation-by-category"); console.log("🔧 Utilisation d'une requête par défaut..."); selectedCase = 'DEFAULT - Requête générale de secours'; From faeb29cef0936389cb330a59a46cef5e51f2b70e Mon Sep 17 00:00:00 2001 From: Imane Amraoui Date: Fri, 5 Jun 2026 13:55:58 +0100 Subject: [PATCH 4/4] Add mediation path stats and mediators by VI category to stats_bdd --- stats_bdd.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/stats_bdd.py b/stats_bdd.py index 0cf36bb..0c1d6bb 100644 --- a/stats_bdd.py +++ b/stats_bdd.py @@ -358,4 +358,60 @@ def count(sparql): print(f" {'VD total (complexes)':<35} {cx_vd_total:>6}") print(f" {'VD avec categorie SKOS':<35} {cx_vd_cat:>6} ({pct_cx_vd}%)") +# --- Top chemins de médiation VI → Médiateur → VD --- +print("\n TOP CHEMINS DE MEDIATION (VI --> Mediateur --> VD)") +print(" " + "-" * 40) +d_chemins = query(f""" +{PREFIX} +SELECT ?viNom ?mediateur ?vdNom (COUNT(DISTINCT ?a) AS ?n) +WHERE {{ + ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; + iadas:hasMediator ?mediateur ; iadas:hasRelation ?rel . + FILTER({FILTER_COMPLEXES}) + FILTER(?mediateur != "N.A.") + ?rel iadas:hasIndependentVariable ?vi ; iadas:hasDependentVariable ?vd . + ?vi iadas:variableName ?viNom . ?vd iadas:variableName ?vdNom . +}} +GROUP BY ?viNom ?mediateur ?vdNom +ORDER BY DESC(?n) +""") +for b in d_chemins["results"]["bindings"][:12]: + vi = b["viNom"]["value"].split("\n")[0].strip()[:22] + med = b["mediateur"]["value"][:22] + vd = b["vdNom"]["value"].split("\n")[0].strip()[:18] + n = b["n"]["value"] + print(f" [{vi}] --[{med}]--> [{vd}] (n={n})") + +# --- Médiateurs par catégorie de VI (SKOS) --- +print("\n MEDIATEURS PAR CATEGORIE DE VI (SKOS)") +print(" " + "-" * 40) +d_med_cat = query(f""" +{PREFIX} +SELECT ?catVI ?mediateur (COUNT(DISTINCT ?a) AS ?n) +WHERE {{ + ?a a iadas:Analysis ; iadas:complexityOfAnalysis ?c ; + iadas:hasMediator ?mediateur ; iadas:hasRelation ?rel . + FILTER({FILTER_COMPLEXES}) + FILTER(?mediateur != "N.A.") + ?rel iadas:hasIndependentVariable ?vi . + ?vi iadas:refersToVariable ?concept . + ?concept skos:broader+ ?top . + ?top skos:prefLabel ?catVI . + FILTER NOT EXISTS {{ ?top skos:broader ?x . FILTER(CONTAINS(STR(?x), 'ACAD-vocab')) }} +}} +GROUP BY ?catVI ?mediateur +ORDER BY ?catVI DESC(?n) +""") +from collections import defaultdict +med_by_cat = defaultdict(list) +for b in d_med_cat["results"]["bindings"]: + cat = b["catVI"]["value"] + med = b["mediateur"]["value"].split("\n")[0].strip()[:35] + n = int(b["n"]["value"]) + med_by_cat[cat].append((med, n)) +for cat, meds in sorted(med_by_cat.items()): + print(f" {cat[:40]}") + for med, n in meds[:4]: + print(f" --> {med:<35} (n={n})") + print("\n" + "=" * 55)