Forschungspipeline
Ziel: Das Ausführen von bash pipeline/run_pipeline.sh aus einem sauberen Checkout plus der rohen
data/ erzeugt alle verarbeiteten Datensätze, Analyseergebnisse, Berichte und
Manuskriptausgaben neu. Jedes Skript, das etwas produziert, das nachgelagert verwendet wird, wird
in Abhängigkeitsreihenfolge von einem Skript unter pipeline/ aufgerufen.
Aufbau
pipeline/
_common.sh # gemeinsame Helfer, von jedem run_*.sh eingebunden (nicht direkt ausführbar)
run_pipeline.sh # Top-Level-Orchestrator: ruft die Phasen-Skripte in Reihenfolge auf
run_preprocessing.sh # Phase: src/prepro/*.R -> output/prepro/
run_analyses.sh # Phase: src/analysis/*.R -> output/analysis/
run_reports.sh # Phase: src/reports/*.qmd -> output/reports/
run_manuscript.sh # Phase: src/manuscript/* -> output/manuscript/
run_script.sh # Führe ein einzelnes .R / .qmd mit derselben Protokollierung aus
Phasennamen folgen den src/-Ordnern des Projekts (z. B. noh-survey verwendet src/manu/
und run_manu.sh). Füge Phasen nur für Ordner hinzu, die existieren; erfinde keine leeren.
Konventionen
#!/usr/bin/env bashundset -euo pipefailin jedem Skript.- Ein Kopfkommentar in jedem Skript: was es tut, die Verwendungszeile
(
bash pipeline/<name>.sh), und welche Phase zuerst gelaufen sein muss (Erfordert ...). - Skripte wechseln per
_common.shin das Projektwurzelverzeichnis, sodass sie von jedem Verzeichnis aus funktionieren. Alle Pfade darin sind relativ zur Projektwurzel. - Protokollierung:
run_pipeline.shexportiertPIPELINE_LOG_DIR=logs/run_pipeline_<Zeitstempel>. Jede Phase erstellt${PIPELINE_LOG_DIR:-logs}/run_<phase>_<zeitstempel>/, sodass Phasen unter dem Pipeline-Lauf verschachtelt sind oder unterlogs/, wenn sie allein ausgeführt werden. Jedes R-Skript / Quarto-Dokument protokolliert in eine eigene<name>_<HH-MM-SS>.txt-Datei. - Bei Fehlern geben
run_r/render_qmddas fehlschlagende Skript, seinen Log-Pfad und die letzten 20 Zeilen des Logs aus und stoppen dann die gesamte Pipeline. - Gruppiere innerhalb einer Phase Aufrufe unter
echo "=== Ebene N: <Grund> ==="-Überschriften nach Abhängigkeitstiefe. Setze einen abschließenden Kommentar bei jedem Aufruf, dessen Abhängigkeit nicht offensichtlich ist (# benötigt output/prepro/redcap-joined.rds). Phasenübergreifende Abhängigkeiten erhalten ihren eigenen beschrifteten Block (z. B. ein Vorverarbeitungsskript, das PCA-Ergebnisse benötigt, kommt in die Analysephase nach PCA). - Jede Phase erstellt mit
mkdir -pdie Ausgabeverzeichnisse, in die sie schreibt. - Quarto rendert in das Quellverzeichnis, daher verschiebt
render_qmddas Ergebnis nachoutput/. Verwende einefor qmd in src/reports/*.qmd-Schleife (Überspringe Vorlagen), wenn alle Berichte in einem Ordner auf die gleiche Weise gerendert werden. - Langsame Schritte erhalten ein
echo "HINWEIS: ... kann lange dauern"vor ihnen. - Halte Aufrufe explizit, ein Skript pro Zeile. Entdecke R-Skripte nicht automatisch mit Platzhaltern: Die Reihenfolge ist der Abhängigkeitsgraph und sollte lesbar sein.
Vorlagen
Kopiere diese aus dem templates/-Verzeichnis dieses Skills und fülle sie aus:
| Vorlage | Wird zu |
|---|---|
_common.sh | pipeline/_common.sh (kopiere unverändert) |
run_pipeline.sh | pipeline/run_pipeline.sh |
run_stage.sh | eine pipeline/run_<phase>.sh pro Phase |
run_script.sh | pipeline/run_script.sh (kopiere unverändert) |
_common.sh bietet:
init_log_dir <phasen-name>: erstellt und setztLOG_DIRrun_r <skript.R> [argumente...]: führt ein R-Skript aus, stdout+stderr in sein Log (Argumente werden zum Log-Namen hinzugefügt, für parametrisierte Läufe wie die Gruppenschleife von noh-survey)run_r_console <skript.R> <stdout-datei>: stdout als Ergebnis gespeichert (z. B.output/manuscript/<name>-console.txt), stderr im Logrender_qmd <dokument.qmd> <ziel-ordner-oder-datei> [quarto argumente...]: rendert und verschiebt die Ausgabe; übergib einen Dateipfad als Ziel, um sie umzubenennen (z. B. ein PDF pro-P gruppe:...)find_quarto: fällt auf das mit RStudio/Positron gebündelte Quarto zurück
Arbeitsablauf
1. Projekt überblicken
- Liste
src/(undfns/,config/) sowie ein eventuell vorhandenespipeline/auf. Wennpipeline/existiert, lies jedes Skript, bevor du etwas änderst, und behalte seinen Stil bei, wo er von diesen Konventionen abweicht (frage nach, bevor du eine etablierte Pipeline migrierst). - Lies die CLAUDE.md / README des Projekts für die angegebene Ausführungsreihenfolge.
2. Abhängigkeitsreihenfolge ermitteln
Finde für jedes .R / .qmd in src/ heraus, was es liest und schreibt:
grep -nE 'readRDS|read_rds|read_csv|read_excel|read\.csv|load\(|fread|readMat|source\(' <datei>
grep -nE 'saveRDS|write_rds|write_csv|ggsave|save\(|writexl|write\.csv|pdf\(|png\(|tiff\(' <datei>
Ordne jede gelesene Datei dem Skript zu, das diese Datei schreibt. Eine gelesene Datei ohne Produzent muss
rohe Eingabe in data/ sein; wenn nicht, markiere sie (es handelt sich entweder um einen fehlenden Pipeline-Schritt
oder um eine manuell erstellte Ausgabe). Weise Ebenen zu: Ebene 0 liest nur data/;
Ebene N liest Ausgaben von Ebenen < N. Zeige dem Benutzer die resultierende Reihenfolge für alle
nicht offensichtlichen Fälle, bevor du Skripte schreibst.
Überspringe archive/, misc/, Vorlagen (*template*) und Entwurfsskripte, sofern der Benutzer
nichts anderes sagt, und liste auf, was du übersprungen hast.
3. Skripte schreiben
Kopiere die Vorlagen, fülle Phasen und Ebenen aus, chmod +x pipeline/*.sh.
4. Abdeckung und Syntax prüfen
bash <dieses-skill-verzeichnis>/scripts/check_coverage.sh <projekt-wurzel>
Dies führt bash -n und shellcheck (falls installiert) auf jedem Pipeline-Skript aus, listet dann
src/-Dateien auf, die von keinem Pipeline-Skript namentlich erwähnt werden. Dateien, die von einer Platzhalter-Schleife
revert werden, werden als nicht erwähnt angezeigt. Überprüfe diese daher manuell. Jede verbleibende Datei wird
entweder zur Pipeline hinzugefügt oder als absichtlich ausgeschlossen bestätigt.
5. Reproduzierbarkeits-Audit
Durchsuche src/ und berichte (korrigiere nicht stillschweigend) jedes dieser Probleme:
setwd(oder absolute Pfade (/Users/,C:/,~/): brechen auf anderen Rechnern- Zufälligkeit (
sample(,rnorm(,boot,simr,set.seedfehlt) ohne einset.seed() - nur interaktiver Code:
View(,file.choose(,readline(,browser( - Ausgaben, die außerhalb von
output/geschrieben werden (außer Quartos Rendern-und-Verschieben) rm(list = ls()): versteckt fehlende Abhängigkeiten, wenn Skripte in einer Sitzung ausgeführt werden
6. Ausführen
Die gesamte Pipeline kann lange dauern und überschreibt output/, frage daher vor dem
Ausführen. Biete an, zuerst eine einzelne Phase oder run_script.sh für eine Datei auszuführen. Um
die Reproduzierbarkeit von Grund auf zu prüfen, verschiebe output/ zur Seite (mv output output.bak),
lösche es nicht, führe dann run_pipeline.sh aus und vergleiche.
7. Dokumentieren
Füge einen Abschnitt "Pipeline ausführen" in der CLAUDE.md / README des Projekts hinzu oder aktualisiere ihn: den einen Befehl, was jede Phase tut und wie man ein einzelnes Skript ausführt.
Hinzufügen eines Skripts zu einer bestehenden Pipeline
- Finde heraus, was das neue Skript liest (Schritt 2) und daher zu welcher Phase und Ebene es gehört.
- Füge dort eine
run_r-Zeile hinzu, mit einem Abhängigkeitskommentar, falls es nicht offensichtlich ist. - Wenn seine Ausgaben von späteren Skripten verwendet werden, überprüfe, ob diese noch in einer späteren Ebene sind.
- Führe
scripts/check_coverage.shaus.