Skip to content

Commit

Permalink
fix: issue #755 for the RELEASE_3_19 branch
Browse files Browse the repository at this point in the history
- `chromatogram()` with `msLevel = 2L` extracts by default signal from all
  isolation windows.
  • Loading branch information
jorainer committed Aug 6, 2024
1 parent 3574486 commit 8f4eac3
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 97 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: xcms
Version: 4.2.2
Version: 4.2.3
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 Expand Up @@ -93,7 +93,7 @@ URL: https://github.com/sneumann/xcms
BugReports: https://github.com/sneumann/xcms/issues/new
VignetteBuilder: knitr
biocViews: ImmunoOncology, MassSpectrometry, Metabolomics
RoxygenNote: 7.3.1
RoxygenNote: 7.3.2
Encoding: UTF-8
Collate:
'AllGenerics.R'
Expand Down
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# xcms 4.2

## Changes in version 4.2.3

- Fix for issue #755: `chromatogram()` with `msLevel = 2L` did return empty
data if parameter `isolationWindowTargetMz` was not specified (or respective
spectra variable was `NA`). By default, now, all MS2 spectra are integrated
if `isolationWindowTargetMz` is not specified.

## Changes in version 4.2.2

- Fix for issue #734: `plot,MsExperiment` is now working with `MsExperiment`
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.

21 changes: 12 additions & 9 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,
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))
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(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 8f4eac3

Please sign in to comment.