lcmsPlot is an R/Bioconductor package designed to generate composable, reproducible, interoperable, and high-quality publication-ready visualisations of Liquid Chromatography-Mass Spectrometry (LC-MS) data and processing results. The package enables users to generate and customise chromatograms, mass traces, spectra, and more with fine-tuned aesthetics and annotation options. By facilitating clear, reproducible, and customisable figures, lcmsPlot enhances interpretation and communication within LC-MS-based metabolomics analyses.
The motivation for developing a dedicated R package for LC–MS data visualization comes from the limitations of existing solutions such as base xcms plotting functions or generic plotting libraries.
While xcms and related tools are powerful for data processing and feature detection, their plotting capabilities are often designed primarily for diagnostic purposes, offering limited flexibility and aesthetics.
Researchers frequently need publication-quality chromatograms, spectra, and comparative visualisations that clearly highlight subtle differences across samples or conditions, which can be cumbersome to generate with the default methods.
The lcmsPlot package addresses this gap by providing:
- A consistent, intuitive, ggplot2-like interface for LC–MS visualizations,
where plot layers are combined with
+. - Streamlined generation of high-quality, customisable plots: chromatograms (BPC, TIC, XIC), mass traces, spectra and mirror plots, intensity maps, peak density, retention-time alignment, and precursor purity.
- Improved reproducibility and reduced need for bespoke scripts.
- Interoperability with raw files, Bioconductor objects, and third-party LC-MS software (see Interoperability).
- Better performance at scale, with parallel extraction (
BPPARAM) and batched plotting of large studies (batch_size+iterate_plot_batches()). - An interactive Shiny app for exploring data without writing code (see Interactive exploration).
Suppose you want to plot chromatograms for a specified m/z and retention time window across all samples, grouped by sample class, with an indicator line at a specific retention time.
With xcms base plotting, this requires several manual steps: extracting chromatograms, arranging plots by sample, handling group colors, and adding annotations:
# Extract chromatograms
chr <- chromatogram(raw_data, mz = c(300, 305), rt = c(2500, 2550))
# Colors for groups
group_cols <- c("KO" = "red", "WT" = "blue")
# Plot setup: one panel per sample
n_samples <- length(chr)
n_col <- ceiling(sqrt(n_samples))
n_row <- ceiling(n_samples / n_col)
par(mfrow = c(n_row, n_col), mar = c(4, 4, 2, 1))
for (i in seq_along(chr)) {
chri <- chr[[i]]
df <- as.data.frame(chri)
group <- pData(raw_data)$sample_group[i]
# Plot
plot(df$rtime, df$intensity,
type = "l", col = group_cols[group],
xlab = "Retention Time (s)", ylab = "Intensity",
main = paste0(names(chr)[i], " (", group, ")"))
# Add vertical line
abline(v = 2520, lty = 2)
}With lcmsPlot, the same task becomes much simpler and more reproducible:
library(lcmsPlot)
lcmsPlot(raw_data, sample_id_column = "sample_name") +
lp_chromatogram(features = rbind(c(
mzmin = 300,
mzmax = 305,
rtmin = 2500,
rtmax = 2550))) +
lp_rt_line(intercept = 2520) +
lp_arrange(group_by = "sample_group") +
lp_facets(facets = "sample_id", ncol = 3)To install this package:
if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("lcmsPlot")To install the development version:
if (!require("remotes", quietly = TRUE))
install.packages("remotes")
remotes::install_github("computational-metabolomics/lcmsPlot")Optional features rely on suggested packages: rawrr for ThermoFisher .raw
files, msPurity for precursor purity plots, and shiny/shinytoastr for
the interactive app.
lcmsPlot plots directly from the data you already have: raw files,
Bioconductor objects, and the results of commonly used LC-MS software. The
same lp_*() layers work for every input, so a figure can be reproduced
whichever tool produced the data.
| Source | Input | How to plot it |
|---|---|---|
| Raw files | mzML, mzXML, netCDF (via mzR) |
lcmsPlot(c("a.mzML", "b.mzML"), metadata = ...) |
ThermoFisher .raw (via rawrr) |
lcmsPlot(c("a.raw", "b.raw")) |
|
| Bioconductor | MsExperiment / XcmsExperiment, XCMSnExp (xcms) |
lcmsPlot(xdata) |
xcmsRaw (legacy xcms) |
lcmsPlot(create_xcms_raw_list(files)) |
|
XChromatograms, XChromatogram, MChromatograms |
lcmsPlot(chrs) |
|
purityA (msPurity) |
lcmsPlot(pa) + lp_purity_*() / lp_isolation_window() |
|
| Compound Discoverer | .cdResult files |
lcmsPlot("study.cdResult") + lp_compound_discoverer() |
| Scripting-node exports | CompoundDiscovererNodeSource() |
|
| MZmine (2+) | Feature lists | MZmineFeatureListsSource() |
| MS-DIAL | Peak tables | MsDialPeaksSource() |
| LipidSearch (4.2, 5.2) | Lipid result files | LipidSearchSource() + lp_lipid_search() |
| Spectral libraries | MSP (via MsBackendMsp) or mzML reference spectra |
lp_spectra(spectral_match_db = "library.msp") for mirror plots |
Results from external software are paired with the raw files they were
computed from (sample_paths), so chromatograms are extracted from the
original data and the peaks reported by the software can be highlighted on
top of them. For example, plotting the six most abundant lipids from a
LipidSearch result:
lipids <- LipidSearchSource(
results_path = "path/to/LIPIDS_POS_5ppm.txt",
sample_paths = c("path/to/sample_1.mzML", "path/to/sample_2.mzML"))
lcmsPlot(lipids) +
lp_lipid_search(lipids_query = "lipid_rank <= 6") +
lp_chromatogram(highlight_peaks = TRUE, ppm = 5) +
lp_grid(rows = "sample_id", cols = "name", free_x = TRUE)or only the compounds checked by hand in Compound Discoverer:
lcmsPlot("study.cdResult") +
lp_compound_discoverer(compounds_query = "checked") +
lp_chromatogram(highlight_peaks = TRUE) +
lp_grid(rows = "sample_id", cols = "name", free_x = TRUE)lcmsPlot ships a ready-made Compound Discoverer post-processing node,
Compounds Chromatograms. It renders one chromatogram per compound from the
original .raw files and adds a clickable plot column to the Compounds table,
so each compound links to its chromatogram inside Compound Discoverer. The
node is installed with the package:
system.file("compound-discoverer-nodes/CompoundsChromatograms",
package = "lcmsPlot")See its README for installation and parameters.
lcmsPlotApp() launches a Shiny dashboard for exploring data without writing
code: BPC/TIC, extracted ion chromatograms, peak density and spectra, with
options for faceting, grouping, legends and titles. It accepts mzML/CDF and
ThermoFisher .raw files, Compound Discoverer .cdResult files, and
XCMSnExp/MsExperiment objects saved as .rds or .RData.
shiny::runApp(lcmsPlotApp())The app needs the suggested packages shiny and shinytoastr.
- Package-level help page:
?\lcmsPlot-package`` - Functions/classes help pages:
?<function> - Vignettes:
browseVignettes("lcmsPlot") - Changes between versions: NEWS.md
Contributions are welcome. Please read CONTRIBUTING.md for the branch naming, commit message, and pull request conventions, and report bugs on the issue tracker.