johnsmithCA-sta/health-report-trend-analysis

Analyse de tendances des bilans de santé pluriannuels : séries temporelles normalisées, tableau de bord hors ligne. Entièrement local · 体检趋势分析

Qu'est-ce que health-report-trend-analysis ?

Ce système permet de transformer des bilans de santé provenant de sources multiples (PDF électroniques, scans, photos) en séries temporelles d'indicateurs standardisés. Il produit un rapport d'analyse de tendances et un tableau de bord interactif de gestion de la santé. Entièrement traité en local, il applique automatiquement l'anonymisation des données et s'adapte dynamiquement : l'ajout d'un nouveau rapport se fait en réexécutant simplement le pipeline. L'utilisateur peut ainsi suivre l'évolution de ses indicateurs clés (glycémie, cholestérol, tension artérielle, etc.) sur plusieurs années, avec une détection des variations significatives (≥20% ou ≥30% de la plage de référence).

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add johnsmithCA-sta/health-report-trend-analysis

Installed? Explore more Recherche et analyse de données skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Système d'Analyse des Tendances des Indicateurs de Bilan de Santé

Objectif

Analyser les bilans de santé pluriannuels (PDF électroniques, scans, photos) en les convertissant en séries temporelles d'indicateurs standardisés. Produit un rapport d'analyse de tendances et un tableau de bord interactif de gestion de la santé. Traitement entièrement local, anonymisation automatique, extensible dynamiquement (ajout d'un nouveau rapport en réexécutant le pipeline).

Mots de déclenchement

  • Bilans de santé des années précédentes / bilans pluriannuels / bilans des années passées
  • Numérisation des bilans de santé / extraction des données de bilan / analyse des bilans
  • Tendances des indicateurs de bilan / analyse des tendances d'indicateurs
  • Comparaison des indicateurs sur les années / comparaison annuelle / évolution annuelle
  • Analyse des résultats de laboratoire / interprétation des analyses / analyse des rapports de laboratoire
  • Scan de bilan de santé / bilan de santé scanné / OCR de scan
  • Photo de bilan de santé / bilan de santé photographié / bilan pris en photo
  • Tableau de bord de gestion de la santé / tableau de bord de données de santé / tableau de bord visuel
  • Tendance de la glycémie / variation de la glycémie / acide urique élevé / tendance des lipides / tendance de la tension
  • Indicateurs anormaux du bilan / interprétation des anomalies / indicateurs anormaux
  • Ajout d'un nouveau bilan / intégration d'un nouveau rapport / ajout d'une nouvelle année de bilan
  • Anonymisation des données de bilan / jeu de données anonymisé / version anonymisée / jeu de données partageable

Préparation de l'environnement

# Dépendances (ignorer si déjà installées) : pymupdf est obligatoire ; Pillow (pour les photos), pyobjc-framework-Vision/Quartz (pour l'OCR, macOS uniquement) sont optionnels
export REPORT_DIR=/chemin/vers/repertoire-bilans      # Répertoire des bilans (contenant les PDF ou les dossiers annuels + JPG)
export WORK_DIR=/chemin/vers/repertoire-travail        # Répertoire de travail (création automatique de data/ et output/)
export PY=/chemin/vers/python                          # Utiliser l'interpréteur Python avec les dépendances

Étape 0 (obligatoire au début de chaque nouvelle session) :

$PY scripts/check_deps.py            # Vérification rapide : ce qui manque, quels scripts sont affectés, comment installer
$PY scripts/check_deps.py --json     # Sortie machine, pour l'automatisation

Code de sortie 0 = dépendances obligatoires présentes, prêt à travailler ; 1 = dépendances obligatoires manquantes (le flux principal ne peut pas être exécuté, suivre les instructions pour installer) ; les dépendances optionnelles manquantes n'affectent que le format d'entrée correspondant, ne bloquent pas le chemin principal pour les PDF électroniques.

Flux d'exécution

Tous les scripts supportent --help ; les paramètres prévalent sur les variables d'environnement ; exécuter sans paramètre = utiliser le comportement par défaut des variables d'environnement.

  1. Identifier le format d'entrée : Parcourir REPORT_DIR
    • Fichiers *.pdf à la racine avec calque de texte → version électronique (traité par parse_reports.py)
    • Fichiers *.pdf à la racine sans calque de texte → scan (traité par vision_ocr.py + extract.py)
    • Sous-dossiers annuels YYYY体检报告/*.JPG → version photo (fusionné par make_year_pdfs.py → OCR → extract.py)
  2. Analyser le PDF électronique (méthode de repérage des coordonnées, voir references/解析与口径.md pour les limites des colonnes) :
    $PY scripts/parse_reports.py                        # → data/reports_raw.json
    $PY scripts/parse_reports.py --year 2027 --dry-run  # Test pour une seule année, sans écrire sur le disque
    
  3. Fusionner les photos en PDF + OCR + extraction (si des répertoires JPG ou des scans existent) :
    $PY scripts/make_year_pdfs.py --year 2015-2020      # Plusieurs JPG d'une année → un seul PDF (correction automatique de rotation des photos en mode paysage)
    $PY scripts/vision_ocr.py <pdf> data/ocr_2022.json  # OCR du scan/photo → JSON avec coordonnées
    $PY scripts/extract.py --year 2022                  # Résultat OCR → indicateurs (stratégie automatique)
    $PY scripts/extract.py --years 2015-2020            # OCR de type dict pour plusieurs années (abréviations + plages de référence déduites)
    
    extract.py paramétré par année, pas besoin de modifier le code pour une nouvelle année : placer dans data/ocr_<année>.json puis exécuter directement --year <année>. Stratégie par défaut auto (si le JSON d'entrée est un dict au niveau supérieur → abbr, s'il est une liste → row), utiliser --strategy pour forcer.
  4. Normaliser + construire le jeu de données (mappage des noms/unités, filtrage des données sales, injection automatique de l'OCR, génération de la version anonymisée) :
    $PY scripts/build_dataset.py
    
    Produit : data/dataset_std.json (version complète, locale) + data/anonymized/anonymized_dataset_anon_shareable.json (version anonymisée, sous-répertoire dédié + lecture seule 444 + partageable)
  5. Analyse des tendances (détection des anomalies selon la plage de référence de l'année, variations significatives ≥20% ou ≥30% de la largeur de la plage, amélioration/détérioration, focalisation sur les 3 dernières années) :
    $PY scripts/trend_analysis.py                        # Par défaut, 3 dernières années
    $PY scripts/trend_analysis.py --focus-years 2020,2023,2026
    
  6. Génération des livrables :
    $PY scripts/report_generator.py    # output/Rapport_analyse_tendances_bilans_sante.md (par défaut avec anonymisation du texte)
    $PY scripts/build_dashboard.py     # output/health_dashboard.html (fichier unique hors ligne)
    

Guide d'ajout d'un nouveau rapport

Pour ajouter un nouveau bilan de santé d'une année, suivre la branche correspondant au format (voir references/Nouveau_rapport_guide_ajout.md) :

  1. Placer le rapport : mettre un *.pdf à la racine de REPORT_DIR, ou créer un sous-dossier YYYY体检报告/ avec des JPG
  2. Identifier le format : vérifier le calque de texte du PDF (len(get_text()) > 0 = version électronique)
    • Version électronique → exécuter directement parse_reports.py ; en cas d'anomalie de colonne, imprimer d'abord un échantillon de coordonnées sur 1 page
    • Scan/photo → make_year_pdfs.py → vision_ocr.py → extract.py --year <année> (ne pas créer de nouveau script par année)
  3. Compléter le dictionnaire (si des indicateurs ne sont pas encore répertoriés) : ajouter une ligne de mappage dans NAME_MAP de indicator_dict.py (voir le journal data/unrecognized)
    $PY scripts/indicator_dict.py --search 尿酸      # Vérifier si déjà répertorié (y compris les alias)
    $PY scripts/indicator_dict.py --validate         # Auto-vérification de l'intégrité du dictionnaire (alias orphelins/clés en double)
    $PY scripts/indicator_dict.py --count            # Nombre total d'indicateurs standard actuels
    
  4. Réexécuter le pipeline : build_dataset → trend_analysis → report_generator → build_dashboard
  5. Validation : vérifier que la nouvelle année apparaît dans trend_analysis.json["years"] et dans la chronologie du tableau de bord ; vérifier les valeurs de 3 indicateurs clés par rapport au rapport ; générer et vérifier la version anonymisée

Règles clés

  • Contrainte stricte de confidentialité (tolérance zéro) : entièrement local, aucune appels réseau sortant dans la compétence ; à la fin de la tâche, la version anonymisée doit être générée et vérifiée (sans nom/numéro de pièce d'identité/téléphone/adresse/hôpital), partager uniquement data/anonymized/anonymized_dataset_anon_shareable.json (isolé en répertoire distinct de la version complète dataset_std.json, lecture seule 444, pour éviter un partage accidentel de la version complète)
  • Vérification de l'anonymisation avant écriture : _write_anon_verified() de build_dataset.py est le seul point de sortie pour la version anonymisée — vérification en mémoire d'abord, écriture sur disque seulement après validation. La version anonymisée est mise en lecture seule 444 dès l'écriture. Si la vérification avait lieu après l'écriture, un fichier contenant des PII serait déjà sur le disque et ne pourrait pas être modifié, le [FAIL] ne serait qu'une alerte a posteriori. Interdiction de contourner ce point de sortie en appelant directement _write_anon() ; --skip-verify est réservé au débogage, les livrables ne doivent pas être partagés
  • Anonymisation du texte du rapport : mask_identity_text de report_generator.py est activé par défaut (masquage des noms d'établissements, noms des médecins, numéros de téléphone, numéros de pièce d'identité) ; --no-mask désactive, réservé à la vérification locale du texte original, ne pas partager les livrables
  • Ajout d'un nouveau rapport annuel : placer dans REPORT_DIR → réexécuter les étapes 2 à 6 ; les indicateurs non répertoriés sont enregistrés dans data/unrecognized, ajouter une ligne dans NAME_MAP de indicator_dict.py
  • Positionnement des données OCR : les indicateurs extraits par OCR sont utilisés uniquement pour l'affichage graphique (marqués en gris Ⓞ), ne participent pas à la détection des variations significatives pour éviter de contaminer les statistiques
  • Focalisation des tendances : la tendance globale et la comparaison début/fin sont basées uniquement sur les années focales (par défaut les 3 dernières années, peut être modifié par --focus-years), les données historiques ne servent que de contexte d'affichage
  • Cohérence des plages de référence : la détection des anomalies utilise la plage de référence du rapport de l'année concernée (adaptation automatique aux changements de réactif, par exemple la bilirubine directe passe de 0.0–4.0 à 1.7–6.8 à partir de 2025)

Livrables

  • output/Rapport_analyse_tendances_bilans_sante.md — Tableau récapitulatif des indicateurs, surlignage des anomalies, interprétation des autorités, recommandations par niveau (mode de vie/alimentation/exercice/consultation médicale), méthodologie
  • output/health_dashboard.html — Vue d'ensemble de la santé, filtres par amélioration/détérioration, graphiques linéaires avec plages de référence, sélection de la période (fichier unique, aucune dépendance externe)
  • data/anonymized/anonymized_dataset_anon_shareable.json — Jeu de données anonymisé partageable

Tableau des scripts

ScriptObjectifParamètres principaux
check_deps.pyAuto-vérification des dépendances (Étape 0)--json --quiet
parse_reports.pyAnalyse des PDF électroniques--report-dir --data-dir --year --out --dry-run
make_year_pdfs.pyFusion JPG annuels en PDF--report-dir --year --out-dir --dry-run
vision_ocr.pyOCR des scans/photospdf out (paramètres positionnels) --dpi --quiet
extract.pyRésultat OCR → indicateurs (paramétré)--year --strategy --ocr-json --out --data-dir --quiet
build_dataset.pyNormalisation + version anonymisée--work-dir --data-dir --out --skip-verify --dry-run
trend_analysis.pyDétection de tendances--work-dir --focus-years --out --dry-run
report_generator.pyRapport Markdown--work-dir --out --no-mask --dry-run
build_dashboard.pyTableau de bord HTML--work-dir --data-dir --out --quiet
indicator_dict.pyDictionnaire des indicateurs (importé)--list --search --count --validate --category (utilisé uniquement en exécution directe)

Code de sortie uniforme à trois états : 0 succès / 1 échec à l'exécution / 2 paramètres ou prérequis non satisfaits.

Documents de référence

DocumentContenu
references/Nouveau_rapport_guide_ajout.mdProcédure complète d'ajout d'un nouveau rapport (format ou année) et dépannage
references/解析与口径.mdCoordonnées des colonnes des PDF électroniques, définitions des plages de référence
references/OCR_methodologie.mdStratégie OCR pour scans/photos, maintenance du tableau de mappage des abréviations
evals/8 tests de régression (dont 3 lignes de défense de confidentialité), eval_loop.py --run pour exécuter

Exemple d'utilisation (session complète)

Utilisateur : « Ajoute le bilan de santé 2027 et mets à jour l'analyse de tendances. »

  1. Étape 0 : python3 scripts/check_deps.py → dépendances obligatoires présentes
  2. Vérifier REPORT_DIR : nouveau fichier trouvé Bilan_sante_270510004567.pdf (électronique, calque de texte complet)
  3. Échantillon pour confirmer les limites des colonnes : imprimer les coordonnées d'une page, cohérent avec references/解析与口径.md → aucun ajustement nécessaire
  4. Exécuter le pipeline :
    export REPORT_DIR=Bilans_Sante WORK_DIR=/chemin/vers/travail
    python3 scripts/parse_reports.py
    python3 scripts/build_dataset.py
    python3 scripts/trend_analysis.py
    python3 scripts/report_generator.py
    python3 scripts/build_dashboard.py
    
  5. Le journal d'analyse montre : 98 indicateurs pour la nouvelle année, 1 nom non reconnu → indicator_dict.py --search confirme qu'il n'est pas répertorié, ajouter 1 ligne dans NAME_MAP puis réexécuter build_dataset
  6. Validation : trend_analysis.json["years"] contient 2027 ; la chronologie du tableau de bord affiche 2027 ; vérifier les valeurs de la glycémie, des lipides, de l'IMC par rapport au rapport ; grep sur la version anonymisée ne trouve aucune information personnelle
  7. Livrables : donner le chemin du rapport et du tableau de bord à l'utilisateur ; expliquer les variations et recommandations pour chaque indicateur anormal en 2027

Discipline de réduction des coûts (obligatoire lors de l'exécution)

  1. Échantillon d'abord : avant d'analyser un nouveau format, imprimer d'abord un échantillon de coordonnées d'une page pour confirmer les limites des colonnes, puis traiter la totalité (éviter de déverser l'intégralité du fichier)
  2. Compression des sorties : les commandes de débogage doivent être uniformément limitées par | head -N / python -c pour une extraction précise, éviter de faire cat d'un gros fichier JSON entier
  3. Isolation des sous-agents : la lecture de gros fichiers / la détection de format doivent être confiées au sous-agent Explore, le thread principal ne reçoit que la conclusion
  4. La validation ne fait qu'une seule capture d'écran finale, les itérations intermédiaires utilisent des vérifications DOM/JS

Journal des modifications

VersionDateChangement
1.1.02026-08-29Réorganisation centralisée de l'ingénierie : ① Tous les 10 scripts supportent --help + argparse + code de sortie à trois états (avant : 0/10, pire score) ; ② Nouveau check_deps.py pour l'auto-vérification des dépendances, ajouté à l'Étape 0 ; ③ Fusion des scripts codés en dur par année extract_2015_2020.py / extract_2022.py en un seul script paramétré extract.py --year (ajout de nouvelle année sans modifier le code, format de sortie identique champ par champ aux anciens scripts) ; ④ Nouveau chapitre ## Mots de déclenchement avec 12 entrées + 8 tests de régression dans evals/ (dont 3 cas de test de la ligne de défense de confidentialité) ; ⑤ Correction de confidentialité : la version anonymisée passe de « écriture puis vérification » à « vérification en mémoire, puis écriture seulement si validée » (auparavant, l'écriture avait lieu avant la vérification, donc un fichier avec des PII était déjà sur le disque et en lecture seule, le [FAIL] n'était qu'une alerte a posteriori) ; ⑥ Correction du code mort dans trend_analysis.py où les éléments de mesure étaient perdus (measurement_items était réinitialisé après ajout, changement pour dédoublonner par clé)
1.0.32026-08-23Correction P2 M-1 (Sécurité de la compétence) : Isolation renforcée de la version anonymisée — anonymized_dataset.json → data/anonymized/anonymized_dataset_anon_shareable.json (sous-répertoire dédié + lecture seule 444 + marquage _anon_shareable), pour éviter que la version complète et la version anonymisée ne soient mélangées et partagées accidentellement ; build_dataset.py ajoute _write_anon() (écriture atomique tmp+replace + chmod 444) ; synchronisation du chemin de la déclaration de confidentialité dans report_generator
1.0.22026-08-17Correction P1 : ajout de verify_anonymized à la fin de build_dataset.py pour une vérification automatique (scan regex des numéros d'identité/téléphone/email/noms d'hôpitaux, sortie avec erreur en cas de détection)
1.0.12026-08-17Correction P0 : report_generator.py ajoute la fonction d'anonymisation mask_identity_text (masquage des numéros de téléphone/pièce d'identité/noms des médecins + généralisation des établissements), anonymisation de la couche d'affichage du texte des résumés/conclusions ; alignement de la déclaration de confidentialité avec la sortie réelle
1.0.02026-08-16Version initiale : Système d'analyse des tendances des indicateurs de bilan de santé

Skills associés