Skip to content

Commit

Permalink
fix: issue #755
Browse files Browse the repository at this point in the history
- `chromatogram` with `msLevel = 2L` does by default extract chromatographic
  data of all MS2 spectra, independently of whether different m/z isolation
  windows were used. For data with isolation windows, the respective isolation
  window can be set/defined with the `isolationWindowTargetMz` parameter.
- Update documentation to describe this behaviour better.
  • Loading branch information
jorainer committed Aug 6, 2024
1 parent b4ed18b commit 986075e
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 94 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: xcms
Version: 4.3.3
Version: 4.3.4
Title: LC-MS and GC-MS Data Analysis
Description: Framework for processing and visualization of chromatographically
separated and single-spectra mass spectral data. Imports from AIA/ANDI NetCDF,
Expand Down
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# xcms 4.3

## Changes in version 4.3.4

- Fix issue #755: `chromatogram()` with `msLevel = 2` fails to extract
chromatographic data if `isolationWindowTargetMz` is not specified or
available (e.g. for MSe data).

## Changes in version 4.3.3

- Support coercing from `XcmsExperiment` to `XCMSnExp` with
Expand Down
2 changes: 1 addition & 1 deletion R/MsExperiment-functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@
if (length(msLevel) != npks)
msLevel <- rep(msLevel[1L], npks)
if (!length(isolationWindow))
isolationWindow <- rep(1L, npks)
isolationWindow <- rep(NA_real_, npks)
if (length(isolationWindow) && length(isolationWindow) != npks)
stop("Length of 'isolationWindow' (if provided) should match the ",
"number of chromatograms to extract.")
Expand Down
18 changes: 10 additions & 8 deletions R/XcmsExperiment.R
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,16 @@
#' associated feature definitions will be included in the returned
#' `XChromatograms`. By default the function returns chromatograms from MS1
#' data, but by setting parameter `msLevel = 2L` it is possible to e.g.
#' extract also MS2 chromatograms. For `msLevel` other than 1 it is in
#' addition important to also specify the `isolationWindowTargetMz` for which
#' MS2 data should be extracted (e.g. for SWATH data MS2 spectra are created
#' for different m/z isolation windows and the `isolationWindowTargetMz`
#' parameter allows to define from which of these the MS2 chromatogram
#' should be extracted.
#' Note that in future more efficient data structures for chromatographic
#' data will be available as well.
#' extract also MS2 chromatograms. By default, with parameter
#' `isolationWindowTargetMz = NULL` or `isolationWindowTargetMz = NA_real_`,
#' data from **all** MS2 spectra will be considered in the chromatogram
#' extraction. If MS2 data was generated within different m/z isolation
#' windows (such as e.g. with Scies SWATH data), the parameter
#' `isolationWindowTargetMz` should be used to ensure signal is only extracted
#' from the respective isolation window. The `isolationWindowTargetMz()`
#' function on the `Spectra` object can be used to inspect/list available
#' isolation windows of a data set. See also the xcms *LC-MS/MS vignette* for
#' examples and details.
#'
#' - `chromPeaks`: returns a `numeric` matrix with the identified
#' chromatographic peaks. Each row represents a chromatographic peak
Expand Down
16 changes: 10 additions & 6 deletions R/functions-utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -791,8 +791,11 @@ groupOverlaps <- function(xmin, xmax) {
#' chromatograms should be extracted.
#'
#' @param pks_tmz `numeric` with the isolation window target m/z in which
#' the (MS2) chromatographic peak was detected. Does not need to be
#' provided for MS1 data.
#' the (MS2) chromatographic peak was detected. For `pks_msl > 1L` only
#' spectra with their `isolationWindowTargetMz` being equal to this value
#' are considered for the chromatogram extraction. Set to
#' `pks_tmz = NA_real_` to use **all** spectra with matching MS level and
#' ignore the isolation window.
#'
#' @param file_idx `integer(1)` allowing to optionally set the index of the
#' file the EIC is from (parameter `fromFile`).
Expand All @@ -803,8 +806,9 @@ groupOverlaps <- function(xmin, xmax) {
#'
#' @noRd
.chromatograms_for_peaks <- function(pd, rt, msl, file_idx = 1L,
tmz = rep(1L, length(pd)), pks, pks_msl,
pks_tmz = rep(1L, nrow(pks)),
tmz = rep(NA_real_, length(pd)), pks,
pks_msl,
pks_tmz = rep(NA_real_, nrow(pks)),
aggregationFun = "sum") {
nr <- nrow(pks)
pks_msl <- as.integer(pks_msl)
Expand All @@ -826,9 +830,9 @@ groupOverlaps <- function(xmin, xmax) {
slot(res[[i]], "msLevel", check = FALSE) <- pks_msl[i]
## if pks_msl > 1: precursor m/z has to match!
keep <- between(rt, pks[i, rtc]) & msl == pks_msl[i]
if (pks_msl[i] > 1L) {
if (pks_msl[i] > 1L && !is.na(pks_tmz[i])) {
## for DIA MS2: spectra have to match the isolation window.
keep <- keep & tmz == pks_tmz[i]
keep <- keep & tmz %in% pks_tmz[i]
}
keep <- which(keep) # the get rid of `NA`.
if (length(keep)) {
Expand Down
18 changes: 10 additions & 8 deletions man/XcmsExperiment.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 11 additions & 8 deletions tests/testthat/test_MsExperiment-functions.R
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,9 @@ test_that(".mse_chromatogram works", {
res <- .mse_chromatogram(mse_dda, rt = rtr, mz = mzr, msLevel = 2L)
expect_true(validObject(res))
expect_equal(msLevel(res[[1L]]), 2L)
expect_true(length(intensity(res[[1L]])) == 0)
expect_true(length(intensity(res[[1L]])) > 0)
expect_equal(msLevel(res[[2L]]), 2L)
expect_true(length(intensity(res[[2L]])) == 0)
expect_true(length(intensity(res[[2L]])) > 0)

## Set isolationWindowTargetMz.
isolationWindowTargetMz(spectra(mse_dda)) <- as.numeric(
Expand All @@ -354,13 +354,16 @@ test_that(".mse_chromatogram works", {
c(81, 83))
rtr <- rbind(c(10, 700),
c(10, 700))
res <- .mse_chromatogram(mse_dda, rt = rtr, mz = mzr, msLevel = 2L,
res <- .mse_chromatogram(mse_dda, rt = rtr, mz = mzr, msLevel = 2L)
res2 <- .mse_chromatogram(mse_dda, rt = rtr, mz = mzr, msLevel = 2L,
isolationWindow = c(56, 40))
expect_true(all(intensity(res[[1L]]) > 0))
expect_true(length(intensity(res[[2L]])) == 0)
res <- .mse_chromatogram(mse_dda, rt = rtr, mz = mzr, msLevel = 2L,
isolationWindow = c(56, 82))
expect_true(all(intensity(res[[1L]]) > 0))
expect_true(all(intensity(res2[[1L]]) > 0))
expect_true(length(intensity(res2[[2L]])) == 0)
expect_true(length(rtime(res[[1L]])) > length(rtime(res2[[1L]])))
res2 <- .mse_chromatogram(mse_dda, rt = rtr, mz = mzr, msLevel = 2L,
isolationWindow = c(56, 82))
expect_true(all(intensity(res2[[1L]]) > 0))
expect_true(length(intensity(res[[1L]])) > length(intensity(res2[[1L]])))
expect_true(all(intensity(res[[2L]]) > 0, na.rm = TRUE))

## Can extract chromatograms if providing the correct isolationWindow.
Expand Down
22 changes: 18 additions & 4 deletions tests/testthat/test_XcmsExperiment.R
Original file line number Diff line number Diff line change
Expand Up @@ -1171,11 +1171,25 @@ test_that("chromatogram,XcmsExperiment and .xmse_extract_chromatograms_old", {
## real MS2 data.
res <- chromatogram(mse_dia, msLevel = 2L, mz = c(50, 300),
rt = c(100, 600))
expect_true(length(intensity(res[[1L]])) == 0)
res <- chromatogram(mse_dia, msLevel = 2L, mz = c(50, 300),
rt = c(100, 600), isolationWindowTargetMz = 270.85,
aggregationFun = "sum")
expect_true(all(intensity(res[[1L]]) > 0))
res2 <- chromatogram(mse_dia, msLevel = 2L, mz = c(50, 300),
rt = c(100, 600), isolationWindowTargetMz = 270.85,
aggregationFun = "sum")
expect_true(all(intensity(res2[[1L]]) > 0))
## have more data points without isolation windows
expect_true(length(intensity(res[[1L]])) > length(intensity(res2[[1L]])))

## fake MS2 data with undefined isolation window.
a <- chromatogram(xmseg, msLevel = 1L,
mz = chromPeaks(xmse)[1:5, c("mzmin", "mzmax")],
rt = chromPeaks(xmse)[1:5, c("rtmin", "rtmax")])
tmp <- xmseg
tmp@spectra$msLevel <- 2L
expect_true(all(is.na(isolationWindowTargetMz(tmp@spectra))))
b <- chromatogram(tmp, msLevel = 2L,
mz = chromPeaks(xmse)[1:5, c("mzmin", "mzmax")],
rt = chromPeaks(xmse)[1:5, c("rtmin", "rtmax")])
expect_equal(intensity(a[[1L]]), intensity(b[[1L]]))

## Defining only mz or rt.
rtr <- c(2600, 2700)
Expand Down
Loading

0 comments on commit 986075e

Please sign in to comment.