BiocStyle::markdown() 

New functionality in xcms

This document describes new functionality and changes to existing functionality in the xcms package introduced during the update to version 3.

library(xcms)
library(RColorBrewer)
register(SerialParam()) 

Modernized user interface

The modernization of the user interface comprises new classes for data representation and new data analysis methods. In addition, the core logic for the data processing has been extracted from the old methods and put into a set of R functions, the so called core API functions (or do_ functions). These functions take standard R data structures as input and return standard R data types as result and can hence be easily included in other R packages.

The new user interface aims at simplifying and streamlining the xcms workflow while guaranteeing data integrity and performance also for large scale metabolomics experiments. Importantly, a simplified access to the original raw data should be provided throughout the whole metabolomics data analysis workflow.

The new interface re-uses objects from the MSnbase Bioconductor package, such as the OnDiskMSnExp object. This object is specifically designed for large scale MS experiments as it initially reads just the scan header information from the mzML while the mz-intensity value pairs from all or from selected spectra of a file are read on demand hence minimizing the memory demand. Also, in contrast to the old xcmsRaw object, the OnDiskMSnExp contains information from all files of an experiment. In addition, all data normalization and adjustment methods implemented in the MSnbase package can be directly applied to the MS data without the need to re-implement such methods in xcms. Results from xcms preprocessings, such as chromatographic peak detection or correspondence are stored into the new XCMSnExp object. This object extends the OnDiskMSnExp object and inherits thus all of its methods including raw data access.

Class and method/function names follow also a new naming convention trying tp avoid the partially confusing nomenclature of the original xcms methods (such as the group method to perform the correspondence of peaks across samples). To distinguish them from mass peaks, the peaks identified by the peak detection in an LS/GC-MS experiment are referred to as chromatographic peaks. The respective method to identify such peaks is hence called findChromPeaks and the identified peaks can be accessed using the XCMSnExp chromPeaks method. The results from an correspondence analysis which aims to match and group chromatographic peaks within and between samples are called features. A feature corresponds to individual ions with a unique mass-to-charge ratio (mz) and a unique retention time (rt). The definition of such mz-rt features (i.e. the result from the groupChromPeaks method) can be accessed via the featureDefinitions method of the XCMSnExp class. Finally, alignment (retention time correction) can be performed using the adjustRtime method.

The settings for any of the new analysis methods are bundled in parameter classes, one class for each method. This encapsulation of the parameters to a function into a parameter class (such as CentWaveParam) avoids busy function calls (with many single parameters) and enables saving, reloading and reusing the settings. In addition, the parameter classes are added, along with other information to the process history of an XCMSnExp object thus providing a detailed documentation of each processing step of an analysis, with the possibility to recall all settings of the performed analyses at any stage. In addition, validation of the parameters can be performed within the parameter object and hence is no longer required in the analysis function.

New naming convention

Peaks identified in LC/GC-MS metabolomics are referred to as chromatographic peaks where possible to avoid any misconceptions with mass peaks identified in mz dimension.

Methods for data analysis from the original xcms code have been renamed to avoid potential confusions:

New data classes

OnDiskMSnExp

This object is defined and documented in the MSnbase package. In brief, it is a container for the full raw data from an MS-based experiment. To keep the memory footprint low the mz and intensity values are only loaded from the raw data files when required. The OnDiskMSnExp object replaces the xcmsRaw object.

XCMSnExp

The XCMSnExp class extends the OnDiskMSnExp object from the MSnbase package and represents a container for the xcms-based preprocessing results while (since it inherits all functionality from its parent class) keeping a direct relation to the (raw) data on which the processing was performed. An additional slot .processHistory in the object allows to keep track of all performed processing steps. Each analysis method, such as findChromPeaks adds an XProcessHistory object which includes also the parameter class passed to the analysis method. Hence not only the time and type of the analysis, but its exact settings are reported within the XCMSnExp object. The XCMSnExp is thus equivalent to the xcmsSet from the original xcms implementation, but keeps in addition a link to the raw data on which the preprocessing was performed.

Chromatogram

The Chromatogram class (available in the MSnbase package since version 2.3.8) allows a data representation that is orthogonal to the Spectrum class (also defined in MSnbase). The Chromatogram class stores retention time and intensity duplets and is designed to accommodate most use cases, from total ion chromatogram, base peak chromatogram to extracted ion chromatogram and SRM/MRM ion traces.

Chromatogram objects can be extracted from XCMSnExp (and MSnExp and OnDiskMSnExp) objects using the chromatogram method.

Note that this class is still considered developmental and might thus undergo some changes in the future.

Binning and missing value imputation functions

The binning/profile matrix generation functions have been completely rewritten. The new binYonX function replaces the binning of intensity values into bins defined by their m/z values implemented in the profBin, profBinLin and profBinLinBase methods. The binYonX function provides also additional functionality:

The missing value imputation logic inherently build into the profBinLin and profBinLinBase methods has been implemented in the imputeLinInterpol function.

The example below illustrates the binning and imputation with the binYtoX and imputeLinInterpol functions. After binning of the test vectors below some of the bins have missing values, for which we impute a value using imputeLinInterpol. By default, binYonX selects the largest value within each bin, but other aggregation methods are also available (i.e. min, max, mean, sum).

## Defining the variables:
set.seed(123)
X <- sort(abs(rnorm(30, mean = 20, sd = 25))) ## 10
Y <- abs(rnorm(30, mean = 50, sd = 30))

## Bin the values in Y into 20 bins defined on X
res <- binYonX(X, Y, nBins = 22)

res 

As a result we get a list with the bin mid-points ($x) and the binned y values ($y).

Next we use two different imputation approaches, a simple linear interpolation and the linear imputation approach that was defined in the profBinLinBase method. The latter performs linear interpolation only considering a certain neighborhood of missing values otherwise replacing the NA with a base value.

## Plot the actual data values.
plot(X, Y, pch = 16, ylim = c(0, max(Y)))
## Visualizing the bins
abline(v = breaks_on_nBins(min(X), max(X), nBins = 22), col = "grey")

## Define colors:
point_colors <- paste0(brewer.pal(4, "Set1"), 80)
## Plot the binned values.
points(x = res$x, y = res$y, col = point_colors[1], pch = 15)

## Perform the linear imputation.
res_lin <- imputeLinInterpol(res$y)

points(x = res$x, y = res_lin, col = point_colors[2], type = "b")

## Perform the linear imputation "linbase"
res_linbase <- imputeLinInterpol(res$y, method = "linbase")
points(x = res$x, y = res_linbase, col = point_colors[3], type = "b", lty = 2) 

The difference between the linear interpolation method lin and linbase is that the latter only performs the linear interpolation in a pre-defined neighborhood of the bin with the missing value (1 by default). The other missing values are set to a base value corresponding to half of the smallest bin value. Both methods thus yield same results, except for bins 15-17 (see Figure above).

Core functionality exposed via simple functions

The core logic from the chromatographic peak detection methods findPeaks.centWave, findPeaks.massifquant, findPeaks.matchedFilter and findPeaks.MSW and from all alignment (group.*) and correspondence (retcor.*) methods has been extracted and put into functions with the common prefix do_findChromPeaks, do_adjustRtime and do_groupChromPeaks, respectively, with the aim, as detailed in issue #30, to separate the core logic from the analysis methods invoked by the users to enable also the use these methods using base R parameters (i.e. without specific classes containing the data such as the xcmsRaw class). This simplifies also the re-use of these functions in other packages and simplifies the future implementation of the peak detection algorithms for e.g. the MSnExp or OnDiskMSnExp objects from the MSnbase Bioconductor package. The implemented functions are:

One possible drawback from the introduction of this new layer is, that more objects get copied by R which could eventually result in a larger memory demand or performance decrease (while no such was decrease was observed up to now).

Usability improvements in the old user interface

Changes due to bug fixes and modified functionality

Differences in linear interpolation of missing values (profBinLin).

From xcms version 1.51.1 on the new binning functions are used, thus, the bug described here are fixed.

Two bugs are present in the profBinLin method (reported as issues #46 and #49 on github) which are fixed in the new binYonX and imputeLinInterpol functions:

The profBinLin method is used in findPeaks.matchedFilter if the profile method is set to "binlin".

The example below illustrates both differences.

## Define a vector with empty values at the end.
X <- 1:11
set.seed(123)
Y <- sort(rnorm(11, mean = 20, sd = 10))
Y[9:11] <- NA
nas <- is.na(Y)
## Do interpolation with profBinLin:
resX <- xcms:::profBinLin(X[!nas], Y[!nas], 5, xstart = min(X),
                          xend = max(X))
resX
res <- binYonX(X, Y, nBins = 5L, shiftByHalfBinSize = TRUE)
resM <- imputeLinInterpol(res$y, method = "lin",
                          noInterpolAtEnds = TRUE)
resM 

Plotting the results helps to better compare the differences. The black points in the figure below represent the actual values of Y and the grey vertical lines the breaks defining the bins. The blue lines and points represent the result from the profBinLin method. The bin values for the first and 4th bin are clearly wrong. The green colored points and lines represent the results from the binYonX and imputeLinInterpol functions (showing the correct binning and interpolation).

plot(x = X, y = Y, pch = 16, ylim = c(0, max(Y, na.rm = TRUE)),
     xlim = c(0, 12))
## Plot the breaks
abline(v = breaks_on_nBins(min(X), max(X), 5L, TRUE), col = "grey")
## Result from profBinLin:
points(x = res$x, y = resX, col = "blue", type = "b")
## Results from imputeLinInterpol
points(x = res$x, y = resM, col = "green", type = "b",
       pch = 4, lty = 2)

Note that by default imputeLinInterpol would also interpolate missing values at the beginning and the end of the provided numeric vector. This can be disabled (to be compliant with profBinLin) by setting parameter noInterpolAtEnds to TRUE (like in the example above).

Differences due to updates in do_findChromPeaks_matchedFilter, respectively findPeaks.matchedFilter.

The original findPeaks.matchedFilter (up to version 1.49.7) had several shortcomings and bugs that have been fixed in the new do_findChromPeaks_matchedFilter method:

A detailed description of tests comparing all implementations is available in issue #52 on github. Note also that in course of these changes also the getEIC method has been updated to use the new binning and missing value imputation function.

While it is strongly discouraged, it is still possible to use to old code (from 1.49.7) by calling useOriginalCode(TRUE).

Differences in findPeaks.massifquant

Differences in obiwarp retention time correction

Retention time correction using the obiwarp method uses the profile matrix (i.e. intensities binned in discrete bins along the mz axis). Profile matrix generation uses now the binYonX method which fixed some problems in the original binning and linear interpolation methods. Thus results might be slightly different.

Also, the retcor.obiwarp method reports (un-rounded) adjusted retention times, but adjusts the retention time of eventually already identified peaks using rounded adjusted retention times. The new adjustRtime method(s) does adjust identified peaks using the reported adjusted retention times (not rounded). This guarantees that e.g. removing retention time adjustment/alignment results from an object restores the object to its initial state (i.e. the adjusted retention times of the identified peaks are reverted to the retention times before alignment). See issue #122 for more details.

retcor.peaksgroups: change in the way how well behaved peak groups are ordered

The retcor.peakgroups defines first the chromatographic peak groups that are used for the alignment of all spectra. Once these are identified, the retention time of the peak with the highest intensity in a sample for a given peak group is returned and the peak groups are ordered increasingly by retention time (which is required for the later fitting of either a polynomial or a linear model to the data). The selection of the retention time of the peak with the highest intensity within a feature (peak group) and samples, denoted as representative peak for a given feature in a sample, ensures that only the retention time of a single peak per sample and feature is selected (note that multiple chromatographic peaks within the same sample can be assigned to a feature). In the original code the ordering of the peak groups was however performed using the median retention time of the complete peak group (which includes also potential additional peaks per sample). This has been changed and the features are ordered now by the median retention time across samples of the representative chromatographic peaks.

scanrange parameter in all findPeaks methods

The scanrange in the findPeaks methods is supposed to enable the peak detection only within a user-defined range of scans. This was however not performed in each method. Due to a bug in findPeaks.matchedFilter's original code the argument was ignored, except if the upper scan number of the user defined range was larger than the total number of available scans (see issue #63). In findPeaks.massifquant the argument was completely ignored (see issue #61) and, while the argument was considered in findPeaks.centWave and feature detection was performed within the specified scan range, but the original @scantime slot was used throughout the code instead of just the scan times for the specified scan indices (see issue #64).

These problems have been fixed in version 1.51.1 by first sub-setting the xcmsRaw object (using the [ method) before actually performing the feature detection.

fillPeaks (fillChromPeaks) differences

In the original fillPeaks.MSW, the mz range from which the signal is to be integrated was defined using

mzarea <- seq(which.min(abs(mzs - peakArea[i, "mzmin"])),
          which.min(abs(mzs - peakArea[i, "mzmax"])))

Depending on the data this could lead to the inclusion of signal in the integration that are just outside of the mz range. In the new fillChromPeaks method signal is integrated only for mz values >= mzmin and <= mzmax thus ensuring that only signal is used that is truly within the peak area defined by columns "mzmin", "mzmax", "rtmin" and "rtmax".

Also, the fillPeaks.chrom method did return "into" and "maxo" values of 0 if no signal was found in the peak area. The new method does not integrate any signal in such cases and does not fill in that peak.

See also issue #130 for more information.

Under the hood changes

These changes and updates will not have any large impact on the day-to-day use of xcms and are listed here for completeness.

Deprecated functions and files

Here we list all of the functions and related files that are deprecated.

Deprecated

xcms 1.49:

xcms 1.51:

Defunct

References



xiaodfeng/DynamicXCMS documentation built on Aug. 6, 2023, 3:02 p.m.