Code
sig <- results |>
dplyr::filter(adj.P.Val < params$fdr_threshold,
abs(logFC) > params$log2fc_threshold)A finished analysis is not a folder of scripts — it is a document that a reviewer, a collaborator, or your future self can regenerate from the raw data with one command, and a data deposit that lets the wider community reuse your work. This closing chapter takes the reproducibility infrastructure built in Chapter 3 (renv, targets, Docker, Git) and turns it outward: writing the report that communicates the analysis, and depositing the data and code so the study meets modern journal and community standards.
Letting the report recompute the analysis. If it reruns peak-picking or model fitting, it drifts out of sync with your pipeline and hides expensive errors. The report reads validated outputs — it never computes them.
By the end of this chapter you will be able to:
targets pipeline so it reads validated outputs instead of recomputing themChapter 3 established the machinery of reproducibility: project structure, renv for package versions, targets for pipeline caching, Docker for system dependencies, and Git for version control. This chapter does not repeat that machinery — it uses it from the perspective of the deliverable.
A mature MS reporting workflow separates three concerns:
| Layer | Owned by | Stored as | Covered in |
|---|---|---|---|
| Computational environment | renv / container |
renv.lock, Dockerfile |
Chapter 3 |
| Analysis pipeline | targets |
_targets.R, cached outputs |
Chapter 3 |
| Human-readable report | Quarto | .qmd, rendered HTML/PDF |
this chapter |
The guiding rule: the report reads, it does not compute. Expensive steps — peak picking, feature detection, model fitting — belong in the pipeline. The report loads validated pipeline outputs and makes the final analytical decisions transparent. This keeps rendering fast, prevents the report and the analysis from drifting out of sync, and means a figure can never silently reflect stale results.
The single most useful Quarto pattern for MS work is the parameterized report: one .qmd template that produces different outputs depending on parameters supplied at render time. It is what lets you run one analysis across many MS runs, generate a QC report per batch, or compare results under different FDR or normalization choices — without copy-pasting the document.
Declare parameters in the YAML header:
---
title: "LC-MS Metabolomics Report"
author: "Your Name"
date: today
params:
feature_matrix: "results/feature_matrix.csv"
fdr_threshold: 0.05
log2fc_threshold: 1.0
batch: "all"
execute:
echo: false
warning: false
---Inside the document, the values are available as params$fdr_threshold, and so on:
sig <- results |>
dplyr::filter(adj.P.Val < params$fdr_threshold,
abs(logFC) > params$log2fc_threshold)Render the same template with different parameters from R or the command line:
# Default parameters
quarto::quarto_render("analysis_report.qmd")
# Stricter FDR, one batch — written to a distinct output file
quarto::quarto_render(
"analysis_report.qmd",
execute_params = list(fdr_threshold = 0.01, batch = "B3"),
output_file = "report_B3_fdr01.html"
)To generate a whole set of reports — for example, one per batch — map over the parameter values:
batches <- c("B1", "B2", "B3")
purrr::walk(batches, function(b) {
quarto::quarto_render(
"analysis_report.qmd",
execute_params = list(batch = b),
output_file = paste0("report_", b, ".html")
)
})Rather than recomputing, load the objects the pipeline already validated:
library(targets)
feature_matrix <- tar_read(feature_matrix)
annotations <- tar_read(annotations)
de_results <- tar_read(de_results)Then make the report itself a pipeline target with tarchetypes::tar_quarto(), so it re-renders only when an upstream dependency changes:
# In _targets.R
library(targets)
library(tarchetypes)
list(
tar_target(raw_data, load_ms_data()),
tar_target(normalised, normalise_matrix(raw_data)),
tar_target(de_results, run_differential(normalised)),
tar_quarto(final_report, path = "reports/analysis_report.qmd")
)This closes the loop: the report is a node in the dependency graph, guaranteed to reflect the current analysis. No more “forgot to regenerate Figure 3.”
Journals have concrete requirements; setting them once in the report saves a round of revisions.
# Consistent, print-quality figure export
ggplot2::ggsave(
"figures/volcano.pdf", # vector format for line art / plots
plot = volcano_plot,
width = 88, height = 88, units = "mm", # single-column width
dpi = 300
)
# Raster fallback for journals that require TIFF/PNG
ggplot2::ggsave("figures/volcano.tiff", volcano_plot,
width = 88, height = 88, units = "mm",
dpi = 300, compression = "lzw")Practical guidance:
theme(text = element_text(size = ...)) rather than scaling the image afterward.gt::gt() or knitr::kable(); export numerical results as CSV alongside the figure so values are machine-readable.viridis) and never encode meaning by colour alone.Published MS data should be Findable, Accessible, Interoperable, and Reusable. Most journals and funders now require deposition to a community repository with a citable accession before publication.
| Repository | Data type | Accession | URL |
|---|---|---|---|
| PRIDE (via ProteomeXchange) | Proteomics raw + identifications | PXD###### | ebi.ac.uk/pride |
| MassIVE (via ProteomeXchange) | Proteomics / any MS | MSV####### | massive.ucsd.edu |
| MetaboLights | Metabolomics raw + metadata | MTBLS#### | ebi.ac.uk/metabolights |
| Metabolomics Workbench | Metabolomics | ST######## | metabolomicsworkbench.org |
| Zenodo | Code + small processed data | DOI | zenodo.org |
Proteomics data goes to a ProteomeXchange partner (PRIDE or MassIVE); metabolomics goes to MetaboLights or Metabolomics Workbench. Deposit analysis code and small processed tables to Zenodo or a tagged GitHub release to mint a citable DOI.
A “complete” ProteomeXchange submission bundles raw and processed evidence with structured metadata:
mzML.mzIdentML (.mzid) or search-engine output, plus the mzTab results table.sdrf.tsv) mapping each raw file to its sample, condition, and label channel.The practical workflow: prepare the files locally, then upload with the PRIDE Submission Tool (px-submission-tool), which validates the bundle and issues a private PXD accession you can share with reviewers before public release. The rpx Bioconductor package lets you programmatically retrieve any ProteomeXchange dataset — useful for reanalysis and for confirming your own deposit:
library(rpx)
px <- PXDataset("PXD000001")
pxfiles(px) # list deposited files
# fn <- pxget(px, "TMT_Erwinia_...mzML") # download a specific fileMetaboLights structures a study around the ISA-Tab framework (Investigation / Study / Assay):
mzML preferred.i_Investigation.txt — study description, contacts, publication.s_Study.txt — sample metadata (organism, factors, collection).a_Assay.txt — per-file acquisition metadata (chromatography, instrument, polarity).m_metabolite.tsv — the metabolite assignment table (feature → annotation, MSI level).Assemble the study offline with the MetaboLights uploader (or the MetaboLights / MsBackendMetaboLights R packages to read studies back), validate against the ISA-Tab schema, and submit for a private MTBLS accession.
Always print session info at the end of a report so results can be debugged and reproduced post hoc.
sessioninfo::session_info()─ Session info ───────────────────────────────────────────────────────────────
setting value
version R version 4.5.1 (2025-06-13 ucrt)
os Windows 11 x64 (build 26200)
system x86_64, mingw32
ui RTerm
language (EN)
collate English_Switzerland.utf8
ctype English_Switzerland.utf8
tz Europe/Zurich
date 2026-07-20
pandoc 3.6.4 @ C:/Users/tranh/AppData/Local/Pandoc/ (via rmarkdown)
quarto 1.9.38 @ C:\\PROGRA~1\\Quarto\\bin\\quarto.exe
─ Packages ───────────────────────────────────────────────────────────────────
package * version date (UTC) lib source
cli 3.6.5 2025-04-23 [1] CRAN (R 4.5.1)
digest 0.6.37 2024-08-19 [1] CRAN (R 4.5.1)
evaluate 1.0.5 2025-08-27 [1] CRAN (R 4.5.1)
fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.5.1)
htmltools 0.5.9 2025-12-04 [1] CRAN (R 4.5.3)
htmlwidgets 1.6.4 2023-12-06 [1] CRAN (R 4.5.1)
jsonlite 2.0.0 2025-03-27 [1] CRAN (R 4.5.1)
knitr 1.51 2025-12-20 [1] CRAN (R 4.5.2)
otel 0.2.0 2025-08-29 [1] CRAN (R 4.5.2)
rlang 1.3.0 2026-07-05 [1] CRAN (R 4.5.3)
rmarkdown 2.31 2026-03-26 [1] CRAN (R 4.5.3)
sessioninfo 1.2.4 2026-06-04 [1] CRAN (R 4.5.3)
xfun 0.60 2026-07-09 [1] CRAN (R 4.5.3)
yaml 2.3.12 2025-12-10 [1] CRAN (R 4.5.3)
[1] C:/Users/tranh/AppData/Local/R/win-library/4.5
[2] C:/Program Files/R/R-4.5.1/library
──────────────────────────────────────────────────────────────────────────────
This chapter turned the reproducibility infrastructure of Chapter 3 into a communicable, shareable deliverable:
tar_quarto() makes the report a pipeline target that reads validated outputs and never drifts from the analysis.Together with the statistical and workflow chapters that precede it, this completes the arc from a raw mzML file to a fully reproducible, publishable result.
fdr_threshold, batch). Render it twice with different values and confirm the outputs differ appropriately._targets.R pipeline (load mzML → build Spectra → export summary CSV) and add the report as a tar_quarto() target. Run tar_visnetwork() and describe the dependency graph.rpx to retrieve the file list for PXD000001, and describe what each file type contributes to a complete ProteomeXchange submission.