Skip to content

Commit 08e1649

Browse files
authored
Merge pull request #761 from sneumann/issue_755
Some updates and bug fixes
2 parents ea3f776 + e39e248 commit 08e1649

19 files changed

+357
-176
lines changed

.github/workflows/check-bioc.yml

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -124,32 +124,7 @@ jobs:
124124
- name: Install macOS system dependencies
125125
if: matrix.config.os == 'macOS-latest'
126126
run: |
127-
## Enable installing XML from source if needed
128-
brew install libxml2
129-
echo "XML_CONFIG=/usr/local/opt/libxml2/bin/xml2-config" >> $GITHUB_ENV
130-
131-
## Required to install magick as noted at
132-
## https://github.com/r-lib/usethis/commit/f1f1e0d10c1ebc75fd4c18fa7e2de4551fd9978f#diff-9bfee71065492f63457918efcd912cf2
133-
brew install imagemagick@6
134-
135-
## For textshaping, required by ragg, and required by pkgdown
136-
brew install harfbuzz fribidi
137-
138-
## For installing usethis's dependency gert
139-
brew install libgit2
140-
141-
## required for ncdf4
142-
## brew install netcdf ## Does not work as it is compiled with gcc
143-
## Use pre-compiled libraries from https://mac.r-project.org/libs-4/
144-
# curl -O https://mac.r-project.org/libs-4/netcdf-4.7.4-darwin.17-x86_64.tar.gz
145-
# tar fvxzm netcdf-4.7.4-darwin.17-x86_64.tar.gz -C /
146-
# rm netcdf-4.7.4-darwin.17-x86_64.tar.gz
147-
# curl -O https://mac.r-project.org/libs-4/hdf5-1.12.0-darwin.17-x86_64.tar.gz
148-
# tar fvxzm hdf5-1.12.0-darwin.17-x86_64.tar.gz -C /
149-
# rm hdf5-1.12.0-darwin.17-x86_64.tar.gz
150-
# curl -O https://mac.r-project.org/libs-4/szip-2.1.1-darwin.17-x86_64.tar.gz
151-
# tar fvxzm szip-2.1.1-darwin.17-x86_64.tar.gz -C /
152-
# rm szip-2.1.1-darwin.17-x86_64.tar.gz
127+
shell: Rscript {0}
153128

154129
- name: Install Windows system dependencies
155130
if: runner.os == 'Windows'

DESCRIPTION

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Package: xcms
2-
Version: 4.3.2
2+
Version: 4.3.3
33
Title: LC-MS and GC-MS Data Analysis
44
Description: Framework for processing and visualization of chromatographically
55
separated and single-spectra mass spectral data. Imports from AIA/ANDI NetCDF,
@@ -54,7 +54,7 @@ Imports:
5454
methods,
5555
Biobase,
5656
BiocGenerics,
57-
ProtGenerics (>= 1.35.4),
57+
ProtGenerics (>= 1.37.1),
5858
lattice,
5959
MassSpecWavelet (>= 1.66.0),
6060
S4Vectors,
@@ -63,7 +63,7 @@ Imports:
6363
MsCoreUtils (>= 1.15.5),
6464
MsFeatures,
6565
MsExperiment (>= 1.5.4),
66-
Spectra (>= 1.13.7),
66+
Spectra (>= 1.15.7),
6767
progress,
6868
RColorBrewer,
6969
MetaboCoreUtils (>= 1.11.2)

NAMESPACE

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import("methods")
44
importMethodsFrom("ProtGenerics", "peaks", "chromatogram", "writeMSData",
55
"polarity<-", "centroided", "isCentroided", "peaks<-",
66
"isolationWindowTargetMz", "quantify", "bin", "spectrapply",
7-
"filterFeatures", "filterMzRange", "filterRt", "filterMz", "filterMsLevel")
7+
"filterFeatures", "filterMzRange", "filterRt", "filterMz", "filterMsLevel",
8+
"estimatePrecursorIntensity")
89
importClassesFrom("ProtGenerics", "Param")
910
importFrom("BiocGenerics", "updateObject", "fileName", "subset",
1011
"dirname", "dirname<-")
@@ -250,7 +251,6 @@ export(
250251
"hasFilledChromPeaks",
251252
"plotAdjustedRtime",
252253
"groupOverlaps",
253-
"estimatePrecursorIntensity",
254254
"featureArea",
255255
"loadXcmsData",
256256
"matchLamasChromPeaks",
@@ -263,6 +263,7 @@ export(
263263
exportMethods(
264264
"showError",
265265
"findChromPeaks",
266+
"estimatePrecursorIntensity",
266267
"groupChromPeaks",
267268
"adjustRtime",
268269
"findChromPeaksIsolationWindow",
@@ -568,6 +569,7 @@ importMethodsFrom("Spectra", "precursorMz")
568569
importMethodsFrom("Spectra", "$")
569570
importMethodsFrom("Spectra", "uniqueMsLevels")
570571
importMethodsFrom("Spectra", "backendBpparam")
572+
importMethodsFrom("Spectra", "estimatePrecursorIntensity")
571573
importFrom("Spectra", "MsBackendMemory", "filterEmptySpectra")
572574

573575
## MsExperiment things

NEWS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
# xcms 4.3
22

3+
## Changes in version 4.3.3
4+
5+
- Fix issue #755: `chromatogram()` with `msLevel = 2` fails to extract
6+
chromatographic data if `isolationWindowTargetMz` is not specified or
7+
available (e.g. for MSe data).
8+
- Support coercing from `XcmsExperiment` to `XCMSnExp` with
9+
`as(object, "XCMSnExp")`.
10+
- Change `estimatePrecursorIntensity()` to a method and add an implementation
11+
for `MsExperiment` objects.
12+
313
## Changes in version 4.3.2
414

515
- Remove data/results import/export functionality as it is being developed in

R/MsExperiment-functions.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@
462462
if (length(msLevel) != npks)
463463
msLevel <- rep(msLevel[1L], npks)
464464
if (!length(isolationWindow))
465-
isolationWindow <- rep(1L, npks)
465+
isolationWindow <- rep(NA_real_, npks)
466466
if (length(isolationWindow) && length(isolationWindow) != npks)
467467
stop("Length of 'isolationWindow' (if provided) should match the ",
468468
"number of chromatograms to extract.")

R/MsExperiment.R

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,16 @@ setMethod(
114114
msLevel = msLevel, isolationWindow = isolationWindowTargetMz,
115115
chunkSize = chunkSize, BPPARAM = BPPARAM)
116116
})
117+
118+
#' @rdname estimatePrecursorIntensity
119+
setMethod(
120+
"estimatePrecursorIntensity", "MsExperiment",
121+
function(object, ppm = 10, tolerance = 0,
122+
method = c("previous", "interpolation"),
123+
BPPARAM = bpparam()) {
124+
method <- match.arg(method)
125+
estimatePrecursorIntensity(spectra(object), ppm = ppm,
126+
tolerance = tolerance, method = method,
127+
f = spectraSampleIndex(object),
128+
BPPARAM = BPPARAM)
129+
})

R/XcmsExperiment-functions.R

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,78 @@ featureArea <- function(object, mzmin = min, mzmax = max, rtmin = min,
11361136
}
11371137

11381138
#' function to create an empty `XcmsExperiment` object
1139+
#'
1140+
#' @noRd
11391141
XcmsExperiment <- function() {
11401142
as(MsExperiment(), "XcmsExperiment")
11411143
}
1144+
1145+
#' function to convert an XcmsExperiment into an XCMSnExp.
1146+
#'
1147+
#' @author Johannes Rainer
1148+
#'
1149+
#' @noRd
1150+
.xcms_experiment_to_xcms_n_exp <- function(from) {
1151+
requireNamespace("MSnbase", quietly = TRUE)
1152+
n <- new("XCMSnExp")
1153+
if (!length(from))
1154+
return(n)
1155+
m <- new("MsFeatureData")
1156+
## works only if we have a MsBackendMzR
1157+
if (!inherits(spectra(from)@backend, "MsBackendMzR"))
1158+
stop("Can not convert 'from' to a 'XCMSnExp' object: 'spectra(x)' uses",
1159+
"an MS backend other than 'MsBackendMzR'. Currently, only",
1160+
" coercion of an object with a 'MsBackendMzR' is supported.")
1161+
## works only if we have an empty processing queue
1162+
if (length(spectra(from)@processingQueue) > 0)
1163+
stop("Can not convert 'from' to a 'XCMSnExp' object: processing queue",
1164+
" of the Spectra object is not empty.")
1165+
## -> OnDiskMSnExp
1166+
n@processingData <- new("MSnProcess",
1167+
processing = paste0("Data converted [", date(), "]"),
1168+
files = fileNames(from),
1169+
smoothed = NA)
1170+
n@phenoData <- new("NAnnotatedDataFrame", as.data.frame(sampleData(from)))
1171+
fd <- as.data.frame(from@spectra@backend@spectraData)
1172+
fnames <- unique(fd$dataStorage)
1173+
fd$fileIdx <- match(fd$dataStorage, fnames)
1174+
fd <- fd[, !colnames(fd) %in% c("dataStorage", "dataOrigin")]
1175+
colnames(fd) <- sub("scanIndex", "spIdx", colnames(fd))
1176+
colnames(fd) <- sub("rtime", "retentionTime", colnames(fd))
1177+
colnames(fd) <- sub("precScanNum", "precursorScanNum", colnames(fd))
1178+
colnames(fd) <- sub("precursorMz", "precursorMZ", colnames(fd))
1179+
fd$spectrum <- seq_len(nrow(fd))
1180+
rownames(fd) <- MSnbase:::formatFileSpectrumNames(
1181+
fd$fileIdx, fd$spIdx,
1182+
max(fd$fileIdx), max(fd$spIdx))
1183+
n@featureData <- new("AnnotatedDataFrame", fd)
1184+
nf <- length(fnames)
1185+
n@experimentData <- new("MIAPE",
1186+
instrumentManufacturer = rep(NA_character_, nf),
1187+
instrumentModel = rep(NA_character_, nf),
1188+
ionSource = rep(NA_character_, nf),
1189+
analyser = rep(NA_character_, nf),
1190+
detectorType = rep(NA_character_, nf))
1191+
n@processingData <- new("MSnProcess",
1192+
processing = paste0("Coercion from ",
1193+
class(from)[1L],
1194+
" [", date(), "]"),
1195+
files = fnames)
1196+
## -> XCMSnExp
1197+
if (hasChromPeaks(from)) {
1198+
chromPeaks(m) <- chromPeaks(from)
1199+
chromPeakData(m) <- chromPeakData(from)
1200+
}
1201+
if (hasAdjustedRtime(from)) {
1202+
art <- fd$retentionTime_adjusted
1203+
names(art) <- rownames(fd)
1204+
adjustedRtime(m) <- split(art, fd$fileIdx)
1205+
}
1206+
if (hasFeatures(from))
1207+
featureDefinitions(m) <- DataFrame(featureDefinitions(from))
1208+
lockEnvironment(m, bindings = TRUE)
1209+
n@msFeatureData <- m
1210+
n@.processHistory <- from@processHistory
1211+
validObject(n)
1212+
n
1213+
}

R/XcmsExperiment.R

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,14 +124,16 @@
124124
#' associated feature definitions will be included in the returned
125125
#' `XChromatograms`. By default the function returns chromatograms from MS1
126126
#' data, but by setting parameter `msLevel = 2L` it is possible to e.g.
127-
#' extract also MS2 chromatograms. For `msLevel` other than 1 it is in
128-
#' addition important to also specify the `isolationWindowTargetMz` for which
129-
#' MS2 data should be extracted (e.g. for SWATH data MS2 spectra are created
130-
#' for different m/z isolation windows and the `isolationWindowTargetMz`
131-
#' parameter allows to define from which of these the MS2 chromatogram
132-
#' should be extracted.
133-
#' Note that in future more efficient data structures for chromatographic
134-
#' data will be available as well.
127+
#' extract also MS2 chromatograms. By default, with parameter
128+
#' `isolationWindowTargetMz = NULL` or `isolationWindowTargetMz = NA_real_`,
129+
#' data from **all** MS2 spectra will be considered in the chromatogram
130+
#' extraction. If MS2 data was generated within different m/z isolation
131+
#' windows (such as e.g. with Scies SWATH data), the parameter
132+
#' `isolationWindowTargetMz` should be used to ensure signal is only extracted
133+
#' from the respective isolation window. The `isolationWindowTargetMz()`
134+
#' function on the `Spectra` object can be used to inspect/list available
135+
#' isolation windows of a data set. See also the xcms *LC-MS/MS vignette* for
136+
#' examples and details.
135137
#'
136138
#' - `chromPeaks`: returns a `numeric` matrix with the identified
137139
#' chromatographic peaks. Each row represents a chromatographic peak

R/functions-OnDiskMSnExp.R

Lines changed: 3 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ setReplaceMethod("dirname", "OnDiskMSnExp", function(path, value) {
722722
#' par(mfrow = c(1, 2))
723723
#' plot(res, precursorIntensity(tmt))
724724
#' plot(res_2, precursorIntensity(tmt))
725-
.estimate_prec_intensity <- function(x, ppm = 10,
725+
.estimate_prec_intensity <- function(x, ppm = 10, tolerance = 0,
726726
method = c("previous", "interpolation")) {
727727
method <- match.arg(method)
728728
pmz <- precursorMz(x)
@@ -739,7 +739,8 @@ setReplaceMethod("dirname", "OnDiskMSnExp", function(path, value) {
739739
before_int <- numeric()
740740
if (length(before_idx)) {
741741
sp <- sps[[before_idx[length(before_idx)]]]
742-
before_idx <- closest(pmz[i], sp@mz, ppm = ppm, tolerance = 0,
742+
before_idx <- closest(pmz[i], sp@mz, ppm = ppm,
743+
tolerance = tolerance,
743744
duplicates = "closest")
744745
if (!is.na(before_idx)) {
745746
before_rt <- sp@rt
@@ -794,48 +795,6 @@ setReplaceMethod("dirname", "OnDiskMSnExp", function(path, value) {
794795
pmi
795796
}
796797

797-
#' @title Estimate precursor intensity for MS level 2 spectra
798-
#'
799-
#' @description
800-
#'
801-
#' `estimatePrecursorIntensity` determines the precursor intensity for a MS 2
802-
#' spectrum based on the intensity of the respective signal from the
803-
#' neighboring MS 1 spectra (i.e. based on the peak with the m/z matching the
804-
#' precursor m/z of the MS 2 spectrum). Based on parameter `method` either the
805-
#' intensity of the peak from the previous MS 1 scan is used
806-
#' (`method = "previous"`) or an interpolation between the intensity from the
807-
#' previous and subsequent MS1 scan is used (`method = "interpolation"`, which
808-
#' considers also the retention times of the two MS1 scans and the retention
809-
#' time of the MS2 spectrum).
810-
#'
811-
#' @param x `OnDiskMSnExp` or `XCMSnExp` object.
812-
#'
813-
#' @param ppm `numeric(1)` defining the maximal acceptable difference (in ppm)
814-
#' of the precursor m/z and the m/z of the corresponding peak in the MS 1
815-
#' scan.
816-
#'
817-
#' @param method `character(1)` defining the method how the precursor intensity
818-
#' should be determined (see description above for details). Defaults to
819-
#' `method = "previous"`.
820-
#'
821-
#' @param BPPARAM parallel processing setup. See [bpparam()] for details.
822-
#'
823-
#' @return `numeric` with length equal to the number of spectra in `x`. `NA` is
824-
#' returned for MS 1 spectra or if no matching peak in a MS 1 scan can be
825-
#' found for an MS 2 spectrum
826-
#'
827-
#' @author Johannes Rainer
828-
#'
829-
#' @md
830-
estimatePrecursorIntensity <- function(x, ppm = 10,
831-
method = c("previous", "interpolation"),
832-
BPPARAM = bpparam()) {
833-
method <- match.arg(method)
834-
unlist(bplapply(.split_by_file2(x, subsetFeatureData = FALSE),
835-
.estimate_prec_intensity, ppm = ppm, method = method,
836-
BPPARAM = BPPARAM), use.names = FALSE)
837-
}
838-
839798
#' Helper function to convert an OnDiskMSnExp to a Spectra object. This will
840799
#' only convert the spectra data, but no sample information.
841800
#'

R/functions-utils.R

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -791,8 +791,11 @@ groupOverlaps <- function(xmin, xmax) {
791791
#' chromatograms should be extracted.
792792
#'
793793
#' @param pks_tmz `numeric` with the isolation window target m/z in which
794-
#' the (MS2) chromatographic peak was detected. Does not need to be
795-
#' provided for MS1 data.
794+
#' the (MS2) chromatographic peak was detected. For `pks_msl > 1L` only
795+
#' spectra with their `isolationWindowTargetMz` being equal to this value
796+
#' are considered for the chromatogram extraction. Set to
797+
#' `pks_tmz = NA_real_` to use **all** spectra with matching MS level and
798+
#' ignore the isolation window.
796799
#'
797800
#' @param file_idx `integer(1)` allowing to optionally set the index of the
798801
#' file the EIC is from (parameter `fromFile`).
@@ -803,8 +806,9 @@ groupOverlaps <- function(xmin, xmax) {
803806
#'
804807
#' @noRd
805808
.chromatograms_for_peaks <- function(pd, rt, msl, file_idx = 1L,
806-
tmz = rep(1L, length(pd)), pks, pks_msl,
807-
pks_tmz = rep(1L, nrow(pks)),
809+
tmz = rep(NA_real_, length(pd)), pks,
810+
pks_msl,
811+
pks_tmz = rep(NA_real_, nrow(pks)),
808812
aggregationFun = "sum") {
809813
nr <- nrow(pks)
810814
pks_msl <- as.integer(pks_msl)
@@ -826,9 +830,9 @@ groupOverlaps <- function(xmin, xmax) {
826830
slot(res[[i]], "msLevel", check = FALSE) <- pks_msl[i]
827831
## if pks_msl > 1: precursor m/z has to match!
828832
keep <- between(rt, pks[i, rtc]) & msl == pks_msl[i]
829-
if (pks_msl[i] > 1L) {
833+
if (pks_msl[i] > 1L && !is.na(pks_tmz[i])) {
830834
## for DIA MS2: spectra have to match the isolation window.
831-
keep <- keep & tmz == pks_tmz[i]
835+
keep <- keep & tmz %in% pks_tmz[i]
832836
}
833837
keep <- which(keep) # the get rid of `NA`.
834838
if (length(keep)) {

0 commit comments

Comments
 (0)