Module 7 · Section 7.4
Rapport reproductible
55 min · niveau avance · dernière révision : 2026-11-01
Objectifs d'apprentissage
- Structurer un rapport scientifique autour de la question, des données, des méthodes, des résultats, des limites et de la disponibilité
- Rédiger un document Quarto ou RMarkdown dont les nombres, les figures et les tableaux sont produits par le code
- Enregistrer les versions, les paramètres et les graines, puis vérifier un manifeste d'empreintes
- Archiver une version taguée avec son environnement et la citer correctement
- Relire un projet et appliquer des critères d'évaluation explicites
Prérequis : 7.2 Pipeline de variants, 7.3 Pipeline RNA-Seq intégré
Quarto 1.5+R 4.4+Git 2.40+
Prérequis
Cette section ferme le module 7. Elle suppose acquis le cadrage du projet et le pipeline de variants de la section 7.2, ainsi que l'analyse transcriptomique de la section 7.3, présentés dans le module 7. Les conventions de reproductibilité — environnement épinglé, historique Git, manifeste SHA-256 — sont celles de 0.1. Les formats de variants de 3.5 et les comptages d'expression ne sont pas réexpliqués : l'objectif est d'assembler un rapport, pas de refaire les étapes amont.
Introduction
Un projet intégré de bioinformatique laisse trois traces : des fichiers de données, du code et un rapport. Les deux premières permettent de recalculer ; la troisième explique ce qui a été demandé, ce qui a été fait et ce que l'on peut en conclure. La reproductibilité exige que les trois restent liés.
L'enjeu biologique est concret. Une figure d'expression différentielle peut montrer un gène surexprimé dans le groupe traité ; encore faut-il savoir combien d'échantillons ont été conservés, quel seuil de significativité a été appliqué, quelle version du modèle a été utilisée et si le résultat résiste au retrait d'un échantillon. Si ces informations manquent, le lecteur ne peut pas distinguer un effet biologique d'un artefact de traitement.
L'enjeu computationnel est double. D'abord, un rapport est un document exécutable : les nombres, les figures et les tableaux doivent être générés par le code, pas recopiés à la main. Ensuite, un rapport est un artefact versionné : il dépend d'un environnement, de paramètres et d'une graine, et il doit pouvoir être reconstruit à partir d'une archive. Un PDF seul ne suffit pas, même signé : il ne contient ni les données ni le code qui l'ont produit.
Cette section ne présente pas de nouveau pipeline. Elle montre comment transformer les sorties des sections 7.2 et 7.3 en un rapport scientifique reproductible, comment le vérifier avant diffusion et comment l'archiver pour qu'il reste citable. L'exemple de bout en bout est construit sur des données synthétiques explicitement étiquetées ; aucun résultat biologique réel n'y est inventé.
Théorie
Les six questions d'un rapport scientifique
Un rapport reproductible suit six questions.
La question énonce le problème biologique, les hypothèses et le critère de décision. « Le traitement modifie-t-il l'expression des gènes de la voie étudiée ? » est une question ; « nous avons lancé DESeq2 » est une méthode. Le critère est fixé avant l'analyse.
Les données documentent la provenance : accession et version, date de téléchargement, licence, empreinte, critères d'inclusion et d'exclusion. Un jeu synthétique est déclaré comme tel. Un fichier nommé latest ne désigne aucune version.
Les méthodes décrivent les outils, leurs versions, les paramètres, la référence, les filtres et le modèle statistique. Il ne s'agit pas de recopier chaque commande, mais de donner assez d'informations pour qu'une personne compétente puisse refaire l'analyse sans deviner.
Les résultats présentent les figures et les tableaux avec leurs unités, leurs effectifs et leur incertitude. Un effet sans intervalle de confiance ni taille d'effet est difficile à interpréter.
Les limites discutent la taille de l'échantillon, les biais de batch, les effets de confusion, la référence choisie, la sensibilité aux seuils et ce qui pourrait renverser la conclusion.
La disponibilité indique où trouver le code, l'environnement, le manifeste et, si possible, les données. Elle donne la licence, le commit, le tag et l'identifiant d'archive. Sans cette section, le rapport n'est pas vérifiable.
Documents exécutables : RMarkdown et Quarto
Un document exécutable mêle texte, code et sorties. RMarkdown associe R, knitr et pandoc ; Quarto généralise le principe avec des fichiers .qmd, un moteur knitr ou Jupyter et un rendu unique par quarto render. Dans les deux cas, le moteur exécute le code et insère les résultats, puis pandoc met en forme.
Le rapport rendu est donc un artefact dérivé. La source de vérité est l'ensemble formé par le fichier .qmd, les données, le code et l'environnement. Un nombre recopié à la main peut diverger silencieusement du résultat.
On peut résumer le rendu par une fonction :
où est le rapport rendu, les données, le code, l'environnement et les paramètres. Reproduire , c'est fixer chacun de ces arguments ; un rendu réussi ne prouve pas que est juste.
Quarto apporte les références croisées et une configuration par projet. Ces commodités ne dispensent pas d'un rendu dans un environnement propre : un cache peut réutiliser une sortie périmée.
Paramétrer le code et fixer les graines
Un rapport paramétré possède une seule source pour chaque seuil. Les paramètres sont déclarés dans l'en-tête YAML, puis utilisés dans le code et dans le texte. Changer alpha ne demande pas de modifier cinq chunks ni de réécrire une phrase à la main : on relance le rendu avec une autre valeur.
params:
alpha: 0.05
min_count: 10
seed: 20261101Avec Quarto, on passe une valeur par quarto render rapport.qmd -P alpha:0.01. En R, les paramètres sont accessibles par params$alpha ; avec Jupyter, le moteur les injecte dans une cellule prévue. Une valeur, un endroit.
Les graines doivent être explicites et enregistrées. En R, set.seed(params$seed) avant tout tirage ; en Python, numpy.random.default_rng(params["seed"]). Une graine non fixée rend un résultat non déterministe.
Le piège est la duplication : un seuil écrit dans le YAML, recopié dans un chunk et répété dans le texte crée trois sources de vérité. Préférez une expression calculée.
Versions, sessionInfo() et manifeste
Un rapport doit dire avec quoi il a été produit. En R, sessionInfo() affiche la version de R, la plateforme et les paquets attachés ; sessioninfo::session_info() détaille davantage et renv::snapshot() fige les dépendances. En Python, sys.version, importlib.metadata.version et un export pip freeze ou conda list --explicit remplissent le même rôle.
La bonne pratique est d'écrire ces informations dans le rapport ou dans un fichier annexe au moment du rendu. Un chunk R peut faire :
writeLines(capture.output(sessionInfo()), "session-info.txt")Le fichier est versionné avec le rapport. Une table des outils reprend les versions qui comptent : aligneur, appelant de variants, modèle différentiel et référence.
Le manifeste complète les versions. Il associe à chaque fichier son chemin relatif et son empreinte SHA-256. La vérification compare l'empreinte recalculée à celle du manifeste. Le taux de couverture s'écrit :
Si est inférieur à 1, le rapport n'est pas vérifié. Une empreinte détecte une modification accidentelle ; elle ne prouve ni l'authenticité, ni la provenance, ni la validité biologique.
Les chemins du manifeste sont relatifs à la racine du projet. Un chemin absolu ne survit pas au changement de machine ; les séparateurs sont normalisés et les empreintes font 64 caractères hexadécimaux.
Figures, légendes et tableaux
Une figure reproductible est produite par le code, avec des paramètres documentés ; elle n'est pas retouchée après export.
Le format dépend de l'usage : SVG ou PDF pour le vectoriel, PNG à 300 points par pouce pour le matriciel. Taille, police et palette sont fixées dans le code, avec une palette lisible en noir et blanc et pour les daltoniens.
La légende est un mini-protocole. Elle indique ce qui est montré, l'unité, l'effectif, la statistique, le test, les paramètres et la définition des barres d'erreur. « Expression des gènes » est un titre ; « log2 du rapport d'expression moyen, trois réplicats par groupe, barres : écart-type, seuil alpha fixé à 0,05 » est une légende. Quarto numérote les figures et les tableaux par des références croisées du type @fig-volcano.
Un tableau reproductible est exporté en TSV ou CSV, puis mis en forme. Les nombres sont arrondis à l'affichage, pas dans l'analyse ; les unités et les valeurs manquantes sont explicites.
Archivage, dépôt Git et citation
Git conserve l'historique, mais un dépôt actif ne suffit pas à citer un état précis. Il faut un tag, par exemple v1.0.0, et le commit associé. git rev-parse HEAD donne l'empreinte complète ; git describe --always --dirty indique si des modifications non validées existent. Le rapport cite le tag et le commit, pas seulement le nom du projet.
L'archive va plus loin : elle fige un paquet téléchargeable, avec le code, le rapport, l'environnement et le manifeste. Zenodo, Software Heritage et OSF remplissent ce rôle et attribuent un identifiant citable. Un conteneur peut compléter l'archive, avec son digest.
La citation se prépare avec un fichier CITATION.cff : auteurs, titre, version, date, dépôt, licence. Une licence explicite est nécessaire : sans elle, le code n'est pas réellement réutilisable, même s'il est public.
Relecture et critères d'évaluation
La relecture technique se fait dans un répertoire neuf. On clone le dépôt au tag, on recrée l'environnement à partir du verrou, on lance quarto render, puis on compare les sorties au manifeste. Cette procédure révèle les dépendances cachées : un fichier absent, un chemin absolu, un paquet installé globalement, une étape manuelle oubliée.
La relecture scientifique vérifie la question, les critères, les méthodes, les résultats et les limites. Elle ne consiste pas à refaire l'analyse, mais à vérifier que le rapport dit assez pour qu'on puisse la refaire. Une question sans critère, une figure sans légende, une limite absente ou une disponibilité vague sont des défauts bloquants.
On peut évaluer un projet avec une grille simple : clarté de la question ; provenance et intégrité des données ; reproductibilité des méthodes ; validité statistique ; intégrité des figures et des tableaux ; discussion des limites ; disponibilité du code et de l'archive ; lisibilité du rapport. Chaque critère doit être relié à une preuve observable, pas à une impression.
Exemple travaillé à la main
Prenons un projet synthétique qui déclare quatre fichiers : data/raw/reads.fastq, reference/ref_demo.fa, results/counts.tsv et metadata/samples.tsv. Trois empreintes correspondent, celle de results/counts.tsv diffère. Le taux de couverture vaut :
Le rapport est bloqué. Comme counts.tsv est dérivé, on le régénère à partir des données brutes et du code, puis on recalcule son empreinte. Si l'écart persiste, la version du pipeline ou les paramètres sont en cause ; si le fichier brut diffère, la question porte sur d'autres données.
Enfin, un plan composé de « Question », « Données », « Méthodes », « Résultats » et « Disponibilité » omet « Limites » : il n'est pas acceptable. On ajoute la section, on discute la taille de l'échantillon et la sensibilité aux seuils, puis on rend de nouveau. Ces contrôles ne disent rien de la biologie ; ils disent si le rapport est vérifiable.
Implémentation
Les exercices construisent quatre contrôles indépendants : normalisation des chemins, résumé des versions, vérification du manifeste et comparaison du plan. Le code ci-dessous montre la fabrication d'un manifeste à partir de contenus textuels. Il hache des octets, pas des caractères affichés, et affiche le nombre d'octets pour rendre visible l'encodage.
Aucune sortie. Exécutez le code pour voir le résultat.
Le code s'exécute dans votre navigateur (Web Worker isolé). Il n'a pas accès au serveur ; l'accès réseau est désactivé pendant l'exécution. Le premier clic sur « Exécuter » télécharge Pyodide depuis jsDelivr (plusieurs mégaoctets, version 0.26.4 épinglée) ; rien n'est chargé avant ce clic.
La sortie vérifiée le 2026-11-01 avec Python 3.13.5 est :
8add5b3bf0a7df65f939b0f2f0650f97ae63c37796bf0d1e769b384e666986cd data/raw/reads.fastq 16
10052d68e5b2d0c43e80669545f0fa1a6e9069ea0888b6f3e03e9553ec1ee167 results/counts.tsv 17
3ebdc67e2df0840903a013b4ab759f446daceba5f0b2571c3a48d87bff7b6ba4 metadata/samples.tsv 35Trois points sont critiques. D'abord, les fins de ligne comptent : un fichier réécrit sous Windows peut passer de \n à \r\n et changer d'empreinte sans que son contenu visible change. Ensuite, les deux espaces entre l'empreinte et le chemin sont ceux attendus par sha256sum -c ; un format maison casse la vérification automatique. Enfin, une empreinte de 64 caractères hexadécimaux est une convention SHA-256 : une chaîne plus courte est probablement tronquée et doit être refusée.
Le rendu Quarto s'insère dans la même logique. Un projet minimal contient rapport.qmd, _quarto.yml, renv.lock ou environment.yml, un manifeste et un répertoire de résultats. La commande quarto render exécute les chunks et écrit le rapport. Pour un contrôle final, on part d'un répertoire de sortie vide et d'un environnement recréé, puis on vérifie les empreintes des fichiers produits. Les commandes suivantes sont illustratives et supposent un système Unix avec sha256sum :
set -euo pipefail
quarto render rapport.qmd
sha256sum -c manifest.sha256
git tag -a v1.0.0 -m "Rapport vérifié"
git rev-parse HEADSous Windows, Get-FileHash -Algorithm SHA256 remplace sha256sum. L'important n'est pas la commande, mais la présence d'une vérification exécutable, reproductible et documentée dans le rapport.
Étude de cas
Exemple synthétique. Le projet projet-integratif est construit pour cette section. Il contient six fichiers FASTQ synthétiques, une référence synthétique courte et une annotation synthétique. Aucun fichier ne provient d'un organisme réel et aucune conclusion biologique n'est tirée des sorties.
La question est volontairement simple : « le traitement synthétique modifie-t-il l'expression des gènes de la voie path_01, et les variants appelés sont-ils cohérents avec les lectures ? » Le critère est fixé avant l'analyse : un gène est déclaré différentiel si sa valeur p ajustée est inférieure à params$alpha et si la valeur absolue de son log2 fold change dépasse 1.
Le pipeline amont est celui des sections 7.2 et 7.3 : contrôle qualité, mapping, appel de variants, comptage et analyse différentielle. Le rapport ne rejoue pas ces étapes ; il les cite, il enregistre leurs versions et il rattache chaque figure à un fichier de résultats.
Le rapport de reproductibilité du mini-projet intervient avant le rendu. Il vérifie que les fichiers déclarés existent, que leurs empreintes correspondent et que les versions sont complètes. Un statut attention interdit de présenter le document comme vérifié, même si le rendu technique fonctionne.
Le plan détaillé est le suivant.
| Section | Contenu | Preuve |
|---|---|---|
| Question | Hypothèses, critère de décision, portée | Texte et paramètres |
| Données | Provenance synthétique, licence, manifeste | manifest.sha256, journal de génération |
| Méthodes | Outils, versions, référence, seuils, graine | Table des versions, session-info.txt |
| Résultats | Variants filtrés, comptages, gènes différentiels | Figures et tableaux générés |
| Limites | Taille de l'échantillon, données synthétiques, seuils | Paragraphe argumenté |
| Disponibilité | Dépôt, tag, archive, licence | URL, commit, identifiant d'archive |
Le fichier rapport.qmd commence par un en-tête qui fixe le format, les paramètres et l'exécution. L'en-tête ci-dessous est un exemple de bloc Quarto, non exécuté dans cette leçon :
---
title: "Projet intégratif — rapport"
subtitle: "Variants et expression sur données synthétiques"
author: "Équipe pédagogique"
date: "2026-11-01"
format:
html:
toc: true
code-fold: true
execute:
echo: false
warning: false
freeze: false
params:
alpha: 0.05
min_count: 10
seed: 20261101
---Le premier chunk écrit les versions et fixe la graine. Le second produit la figure principale, avec une légende et un texte alternatif. Les sorties ne sont pas montrées : le bloc est illustratif et dépend de fichiers synthétiques qui ne sont pas livrés avec la leçon.
#| label: setup
#| include: false
set.seed(params$seed)
writeLines(capture.output(sessionInfo()), "session-info.txt")#| label: fig-volcano
#| fig-cap: "Volcan synthétique : log2 du rapport d'expression contre -log10 de la valeur p ajustée. Chaque point est un gène synthétique ; les seuils viennent des paramètres du rapport."
#| fig-alt: "Nuage de points opposant le log2 du rapport d'expression à la significativité ajustée, avec deux lignes verticales aux seuils de log2 fold change."
#| echo: false
res <- read.delim("results/deseq2.tsv")
res$significant <- res$padj < params$alpha & abs(res$log2FoldChange) >= 1
plot(
res$log2FoldChange,
-log10(res$padj),
pch = 19,
col = ifelse(res$significant, "#c0392b", "#7f8c8d"),
xlab = "log2 fold change",
ylab = "-log10(p ajustée)"
)
abline(v = c(-1, 1), lty = 2)Les résultats attendus sont des artefacts : un rapport HTML, session-info.txt, un manifeste vérifiable et des figures légendées, avec le tag, le commit et l'archive. Si un fichier de résultats manque, le rendu doit échouer ou le signaler.
L'interprétation reste limitée par construction. Les données sont synthétiques, l'échantillon est petit et la voie path_01 est une convention de démonstration. Une différence observée ne prouve rien sur Escherichia coli ni sur un traitement réel. Le rapport doit le dire dans la section Limites, et la section Disponibilité doit préciser que les données sont régénérables par un script.
Un résultat synthétique négatif ne rend pas le rapport inutile : montrez la puissance limitée, la distribution des valeurs p et l'effet des seuils. La section Limites doit distinguer l'absence d'effet de l'absence de puissance.
Erreurs fréquentes
Quiz
Exercices
Énoncé
Écrire sanitize_paths(paths), qui convertit une liste de chemins en chemins relatifs normalisés, puis session_summary(versions), qui résume des versions d'outils. Pour les chemins : séparateurs Windows en /, segments vides et . supprimés, .. résolus sans sortir de la racine, doublons éliminés en gardant le premier ; refuser un chemin absolu, un chemin commençant par ~, une chaîne vide et une sortie de racine. Pour les versions : x.y.z complet avec v initial toléré ; x ou x.y dans coarse, une valeur non numérique comme latest dans unpinned, une casse différente dans duplicates ; text est trié par outil. Lever TypeError ou ValueError selon le cas.
Comment vérifier votre travail
Les tests se trouvent dans exercises/module-7/7.4-rapport-reproductible/test_7_4.py. Depuis la racine du dépôt :
python -m pytest exercises/module-7/7.4-rapport-reproductible -qCorrigé verrouillé
Le corrigé est chargé uniquement après confirmation. Il n'est pas présent dans la page avant cette action.
Énoncé
Écrire verify_manifest(manifest, root=None), qui vérifie une liste d'entrées path et sha256, puis report_outline(sections), qui compare des titres au plan d'un rapport. Pour le manifeste : normaliser les chemins, exiger 64 caractères hexadécimaux, signaler doublons, entrées mal formées et empreintes invalides sans exception ; avec root, placer un fichier absent dans missing et une empreinte différente dans mismatched ; un manifeste vide n'est pas valide. Pour le plan : Question, Données, Méthodes, Résultats, Limites, Disponibilité ; ignorer casse et accents, accepter « jeux de données » ou « disponibilité du code », autoriser les sections hors plan comme « Annexes » et vérifier l'ordre. Le résultat contient ok, outline, present, missing, extra, duplicates, coverage, order, order_ok et warnings.
Comment vérifier votre travail
Les tests se trouvent dans exercises/module-7/7.4-rapport-reproductible/test_7_4.py. Depuis la racine du dépôt :
python -m pytest exercises/module-7/7.4-rapport-reproductible -qCorrigé verrouillé
Le corrigé est chargé uniquement après confirmation. Il n'est pas présent dans la page avant cette action.
Énoncé
Mini-projet : rapport de reproductibilité. Écrire reproducibility_report(manifest, versions, root=None) qui combine verify_manifest et session_summary. Le rapport contient ok, status (ok ou attention), n_files, n_valid_files, n_tools, manifest_ok, session_ok, files, tools, session_text, duplicates, invalid_paths, invalid_hashes, missing, mismatched, unpinned, coarse et issues. Il est ok seulement si les deux contrôles passent. Lever TypeError si les conteneurs sont mal typés et ValueError s'ils sont vides ; les problèmes d'une entrée restent dans issues sans interrompre le calcul.
Comment vérifier votre travail
Les tests se trouvent dans exercises/module-7/7.4-rapport-reproductible/projet/test_projet_7_4.py. Depuis la racine du dépôt :
python -m pytest exercises/module-7/7.4-rapport-reproductible/projet -qCorrigé verrouillé
Le corrigé est chargé uniquement après confirmation. Il n'est pas présent dans la page avant cette action.
Résumé
- Un rapport reproductible répond à six questions : question, données, méthodes, résultats, limites, disponibilité.
- Quarto et RMarkdown exécutent le code et insèrent les sorties ; le rapport rendu est un artefact dérivé, jamais la source de vérité.
- Un rapport paramétré déclare ses seuils une seule fois et fixe une graine explicite.
sessionInfo()et un verrou d'environnement enregistrent les versions ; un manifeste SHA-256 vérifie l'intégrité des fichiers.- Les figures et les tableaux sont générés par le code, avec unités, effectifs, incertitude et légende autosuffisante.
- Un tag Git, un identifiant d'archive et un fichier
CITATION.cffrendent le rapport citable. - La relecture se fait dans un répertoire neuf, avec un environnement recréé et une vérification du manifeste.
- La reproductibilité est une condition de vérification : elle ne prouve pas la validité biologique.
Références
- Quarto. Quarto Documentation. https://quarto.org/docs/
- R Markdown. R Markdown Documentation. https://rmarkdown.rstudio.com/
- Xie, Y. (2015). Dynamic Documents with R and knitr (2e éd.). Chapman & Hall/CRC.
- Wilkinson, M. D. et al. (2016). The FAIR Guiding Principles for scientific data management and stewardship. Scientific Data, 3, 160018.
- The Turing Way Community (2022). The Turing Way: A Handbook for Reproducible, Ethical and Collaborative Data Science. https://the-turing-way.netlify.app
- Git. Git Documentation. https://git-scm.com/doc
- R Core Team (2024). R: A Language and Environment for Statistical Computing. https://www.R-project.org/