Pipeline de recherche
Objectif : exécuter bash pipeline/run_pipeline.sh à partir d'une copie propre du projet et des données brutes data/ recrée chaque jeu de données traité, résultat d'analyse, rapport et sortie du manuscrit. Chaque script qui produit quelque chose utilisé en aval est appelé, dans l'ordre des dépendances, par un script dans pipeline/.
Structure
pipeline/
_common.sh # helpers partagés, sourcés par chaque run_*.sh (non exécuté directement)
run_pipeline.sh # orchestrateur principal : appelle les scripts d'étape dans l'ordre
run_preprocessing.sh # étape : src/prepro/*.R -> output/prepro/
run_analyses.sh # étape : src/analysis/*.R -> output/analysis/
run_reports.sh # étape : src/reports/*.qmd -> output/reports/
run_manuscript.sh # étape : src/manuscript/* -> output/manuscript/
run_script.sh # exécute un seul .R / .qmd avec la même journalisation
Les noms des étapes suivent les dossiers src/ du projet (par exemple noh-survey utilise src/manu/ et run_manu.sh). N'ajoutez des étapes que pour les dossiers qui existent ; n'inventez pas d'étapes vides.
Conventions
#!/usr/bin/env bashetset -euo pipefaildans chaque script.- Un commentaire d'en-tête sur chaque script : ce qu'il fait, la ligne d'utilisation (
bash pipeline/<nom>.sh), et quelle étape doit avoir été exécutée en premier (Requiert ...). - Les scripts
cdvers la racine du projet via_common.sh, afin qu'ils fonctionnent depuis n'importe quel répertoire. Tous les chemins internes sont relatifs à la racine du projet. - Journalisation :
run_pipeline.shexportePIPELINE_LOG_DIR=logs/run_pipeline_<horodatage>. Chaque étape crée${PIPELINE_LOG_DIR:-logs}/run_<étape>_<horodatage>/, de sorte que les étapes s'imbriquent sous l'exécution du pipeline, ou aillent souslogs/lorsqu'elles sont exécutées seules. Chaque script R / document Quarto journalise dans son propre<nom>_<HH-MM-SS>.txt. - En cas d'échec,
run_r/render_qmdaffiche le script en échec, son chemin de journal, et les 20 dernières lignes du journal, puis arrête tout le pipeline. - Dans une étape, regroupez les appels sous des en-têtes
echo "=== Couche N : <pourquoi> ==="par profondeur de dépendance. Ajoutez un commentaire de fin sur tout appel dont la dépendance n'est pas évidente (# nécessite output/prepro/redcap-joined.rds). Les dépendances inter-étapes ont leur propre bloc étiqueté (par exemple, un script de pré-traitement qui nécessite les résultats d'une ACP va dans l'étape d'analyse après l'ACP). - Chaque étape
mkdir -ples répertoires de sortie qu'elle écrit. - Quarto effectue le rendu dans le dossier source, donc
render_qmddéplace le résultat dansoutput/. Utilisez une bouclefor qmd in src/reports/*.qmd(en ignorant les modèles) lorsque chaque rapport d'un dossier est rendu de la même manière. - Les étapes lentes reçoivent un
echo "NOTE : ... peut prendre beaucoup de temps"avant elles. - Gardez les appels explicites, une ligne par script. Ne découvrez pas automatiquement les scripts R avec des globs : l'ordre est le graphe de dépendances, et il doit être lisible.
Modèles
Copiez ces modèles depuis le répertoire templates/ de cette compétence et remplissez-les :
| Modèle | Devient |
|---|---|
_common.sh | pipeline/_common.sh (copier tel quel) |
run_pipeline.sh | pipeline/run_pipeline.sh |
run_stage.sh | un pipeline/run_<étape>.sh par étape |
run_script.sh | pipeline/run_script.sh (copier tel quel) |
_common.sh fournit :
init_log_dir <nom-étape>: crée et définitLOG_DIRrun_r <script.R> [args...]: exécute un script R, stdout+stderr vers son journal (les arguments sont ajoutés au nom du journal, pour les exécutions paramétrées comme la boucle de groupe de noh-survey)run_r_console <script.R> <fichier-stdout>: stdout sauvegardé comme livrable (par exempleoutput/manuscript/<nom>-console.txt), stderr vers le journalrender_qmd <doc.qmd> <dossier-ou-fichier-dest> [args quarto...]: effectue le rendu et déplace la sortie ; passez un chemin de fichier comme destination pour le renommer (par exemple un PDF par-P group:...)find_quarto: utilise par défaut le Quarto fourni avec RStudio/Positron
Flux de travail
1. Examiner le projet
- Listez
src/(etfns/,config/) et toutpipeline/existant. Sipipeline/existe, lisez chaque script avant de modifier quoi que ce soit, et conservez son style là où il diffère de ces conventions (demandez avant de migrer un pipeline établi). - Lisez le CLAUDE.md / README du projet pour l'ordre d'exécution déclaré.
2. Déterminer l'ordre des dépendances
Pour chaque .R / .qmd dans src/, trouvez ce qu'il lit et écrit :
grep -nE 'readRDS|read_rds|read_csv|read_excel|read\.csv|load\(|fread|readMat|source\(' <fichier>
grep -nE 'saveRDS|write_rds|write_csv|ggsave|save\(|writexl|write\.csv|pdf\(|png\(|tiff\(' <fichier>
Associez chaque lecture au script qui écrit ce fichier. Une lecture sans producteur doit être une entrée brute dans data/ ; si ce n'est pas le cas, signalez-le (c'est soit une étape manquante du pipeline, soit une sortie fabriquée à la main). Attribuez des couches : Couche 0 lit uniquement data/ ; Couche N lit les sorties des couches < N. Montrez à l'utilisateur l'ordre résultant pour tout cas non évident avant d'écrire les scripts.
Ignorez archive/, misc/, les modèles (*template*) et les scripts de brouillon, sauf indication contraire de l'utilisateur, et listez ce que vous avez ignoré.
3. Écrire les scripts
Copiez les modèles, remplissez les étapes et les couches, chmod +x pipeline/*.sh.
4. Vérifier la couverture et la syntaxe
bash <chemin-vers-ce-dossier-de-competence>/scripts/check_coverage.sh <racine-du-projet>
Cela exécute bash -n et shellcheck (si installé) sur chaque script du pipeline, puis liste les fichiers src/ qu'aucun script du pipeline ne mentionne par leur nom. Les fichiers rendus par une boucle glob apparaissent comme non mentionnés, donc vérifiez-les manuellement. Chaque fichier restant est soit ajouté au pipeline, soit confirmé comme intentionnellement exclu.
5. Audit de reproductibilité
Recherchez dans src/ et signalez (ne corrigez pas silencieusement) l'un des éléments suivants :
setwd(ou chemins absolus (/Users/,C:/,~/) : cassent sur d'autres machines- aléatoire (
sample(,rnorm(,boot,simr,set.seedmanquant) sansset.seed() - code interactif uniquement :
View(,file.choose(,readline(,browser( - sorties écrites en dehors de
output/(sauf le rendu puis déplacement de Quarto) rm(list = ls()): masque les dépendances manquantes lorsque les scripts sont exécutés dans une même session
6. Exécuter
Le pipeline complet peut prendre beaucoup de temps et écrase output/, donc demandez avant de l'exécuter. Proposez d'exécuter d'abord une seule étape ou run_script.sh sur un seul fichier. Pour vérifier la reproductibilité à partir de zéro, déplacez output/ de côté (mv output output.bak), ne le supprimez pas, puis exécutez run_pipeline.sh et comparez.
7. Documenter
Ajoutez ou mettez à jour une section "Exécuter le pipeline" dans le CLAUDE.md / README du projet : la commande unique, ce que fait chaque étape et comment exécuter un script.
Ajouter un script à un pipeline existant
- Trouvez ce que le nouveau script lit (étape 2) et donc à quelle étape et couche il appartient.
- Ajoutez une ligne
run_rlà, avec un commentaire de dépendance si ce n'est pas évident. - Si ses sorties alimentent des scripts ultérieurs, vérifiez qu'ils sont toujours dans une couche ultérieure.
- Exécutez
scripts/check_coverage.sh.