diff --git a/DESCRIPTION b/DESCRIPTION index e370ec7e..df989c20 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,5 +1,5 @@ Package: xcms -Version: 4.3.1 +Version: 4.3.2 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, @@ -60,10 +60,10 @@ Imports: S4Vectors, IRanges, SummarizedExperiment, - MsCoreUtils (>= 1.15.5), + MsCoreUtils (>= 1.15.7), MsFeatures, MsExperiment (>= 1.5.4), - Spectra (>= 1.13.7), + Spectra (>= 1.15.3), progress, jsonlite, RColorBrewer, diff --git a/NAMESPACE b/NAMESPACE index 3b122388..6cb20942 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -33,7 +33,7 @@ importFrom("SummarizedExperiment", "rowData") importFrom("SummarizedExperiment", "rowData<-") importFrom("SummarizedExperiment", "assay") importFrom("MsCoreUtils", "rbindFill", "closest", "i2index", "sumi", "between", - "maxi", "breaks_ppm", "force_sorted") + "maxi", "breaks_ppm", "force_sorted", "common_path") importFrom("RColorBrewer", "brewer.pal") importFrom("graphics", "image", "boxplot", "matplot", "rect", "axis", @@ -52,7 +52,7 @@ importFrom("stats", "aov", "approx", "convolve", "cor", "deriv3", "rnorm", "runif", "dbeta", "resid") importFrom("utils", "flush.console", "head", "object.size", "packageVersion", "read.csv", "tail", "write.csv", - "write.table", "capture.output", "data") + "write.table", "capture.output", "data", "read.table") importFrom("MassSpecWavelet", "peakDetectionCWT", "tuneInPeakInfo") @@ -254,7 +254,8 @@ export( "loadXcmsData", "matchLamasChromPeaks", "summarizeLamaMatch", - "matchedRtimes" + "matchedRtimes", + "XcmsExperiment" ) ## New analysis methods @@ -558,7 +559,7 @@ importMethodsFrom("Spectra", "uniqueMsLevels") importMethodsFrom("Spectra", "selectSpectraVariables") importMethodsFrom("Spectra", "setBackend") importMethodsFrom("Spectra", "dataOrigin") -importMethodsFrom("Spectra", "dataStorage") +importMethodsFrom("Spectra", "dataStorage", "dataStorage<-") importMethodsFrom("Spectra", "spectraVariables") importMethodsFrom("Spectra", "rtime<-") importMethodsFrom("Spectra", "ionCount") @@ -566,7 +567,9 @@ importMethodsFrom("Spectra", "precursorMz") importMethodsFrom("Spectra", "$") importMethodsFrom("Spectra", "uniqueMsLevels") importMethodsFrom("Spectra", "backendBpparam") -importFrom("Spectra", "MsBackendMemory") +importFrom("Spectra", "MsBackendMemory", "dataStorageBasePath", + "dataStorageBasePath<-", "processingChunkSize", + "dropNaSpectraVariables", "MsBackendMzR", "filterEmptySpectra") ## MsExperiment things importClassesFrom("MsExperiment", "MsExperiment") @@ -590,12 +593,15 @@ exportMethods("filterMzRange") exportMethods("fromFile") exportMethods("fileNames") -## saving xcms objects things +## saving/loading xcms objects things importFrom("jsonlite", "serializeJSON", "write_json", "unserializeJSON", "read_json") +importFrom("stats", "setNames") +importFrom("MsCoreUtils", "between") export("RDataParam") export("PlainTextParam") -exportMethods("storeResults") +exportMethods("storeResults", "loadResults") + ## filtering features things importFrom("MetaboCoreUtils", "rowRsd", "rowDratio", "rowPercentMissing", diff --git a/NEWS.md b/NEWS.md index ecb3f7b3..a6544849 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,10 @@ # xcms 4.3 +## Changes in version 4.3.2 + +- Addition of generic function `loadResults()`and method for import using + `RDataParam` and `PlaintTextParam`. + ## Changes in version 4.3.1 - Support excluding samples or sample groups from defining features with @@ -8,7 +13,6 @@ - Fix in `dropFeatureDefinitions()` that was not correctly removing additional metadata from gap-filled chromatographic peaks. - # xcms 4.1 ## Changes in version 4.1.14 diff --git a/R/AllGenerics.R b/R/AllGenerics.R index fbf47a96..66286bc7 100644 --- a/R/AllGenerics.R +++ b/R/AllGenerics.R @@ -1486,6 +1486,66 @@ setGeneric("kNN<-", function(object, value) standardGeneric("kNN<-")) ## L setGeneric("levelplot", function(x, data, ...) standardGeneric("levelplot")) +#' @title Import various file format as XcmsExperiment object +#' +#' @description +#' +#' The `loadResults` function allows to import and create an `XcmsExperiment` +#' object from a file. Multiple formats for importing are available and can be +#' defined by the `param` argument. +#' +#' Supported `param` objects are: +#' +#' - [`RDataParam`]: Import an `MsExperiment` or `XcmsExperiment` object from +#' an .RData file. +#' +#' - [`PlainTextParam`]: Import an `MsExperiment` or `XcmsExperiment` object +#' from a folder of text files. +#' +#' - `MzTabParam`: Load a MzTab-m file (to be defined). +#' +#' For specific examples, see the help pages of the individual parameter classes +#' listed above. +#' +#' @param object Define the class of the object to be imported. It can be one +#' of the following classes: [`XcmsExperiment()`], [`MsExperiment()`] for now, +#' more class will be supported in the future. +#' +#' @param param The parameter object selecting and configuring the format for +#' saving. It can be one of the following classes: [`RDataParam`], +#' [`PlainTextParam`], or `MzTabParam`. +#' +#' @param ... Optional parameters. +#' +#' @note +#' The same `param` object can be used to import as it was used for export with +#' the `storeResults()` function. +#' +#' @name loadResults +#' +#' @author Philippine Louail +#' +#' @examples +#' ## Load a test data set with detected peaks +#' faahko_sub <- loadXcmsData("faahko_sub2") +#' +#' ## Save as RData +#' param <- RDataParam(fileName = "example_xcms_object") +#' storeResults(object = faahko_sub, param = param) +#' +#' ## Load this saved dataset +#' xcmse <- loadResults(object = XcmsExperiment(),param = param) +#' +#' ## Save as a collection of plain text files +#' pth = file.path(tempdir(), "test") +#' param <- PlainTextParam(path = pth) +#' storeResults(object = faahko_sub, param = param) +#' +#' ## Load this saved dataset +#' faahko_load <- loadResults(object= XcmsExperiment(), param = param) +#' +#' @md +setGeneric("loadResults", function(object, param,...) standardGeneric("loadResults")) setGeneric("localAlignment", function(object) standardGeneric("localAlignment")) setGeneric("localAlignment<-", function(object, value) standardGeneric("localAlignment<-")) setGeneric("loadRaw", function(object, ...) standardGeneric("loadRaw")) diff --git a/R/PlainTextParam.R b/R/PlainTextParam.R index 4eabe7b8..060450ac 100644 --- a/R/PlainTextParam.R +++ b/R/PlainTextParam.R @@ -1,5 +1,5 @@ #' @include XcmsExperiment.R - +#' #' @title Store contents of `MsExperiment` and `XcmsExperiment` objects as #' plain text files #' @@ -7,68 +7,97 @@ #' #' @export #' -#' @family xcms result export formats. +#' @family xcms result export and import formats. #' #' @description -#' The `PlainTextParam` class and method enable users to save `MsExperiment` or -#' `XcmsExperiment` objects as collections of plain text files in a specified -#' folder. Note that, while for all xcms results within the `XcmsExperiment` can -#' and will be exported, the full raw MS data (of the object's `Spectra` object) -#' will currently not be exported in plain text format. For `Spectra` using the -#' [MsBackendMzR()] backend, the names of the raw data files will however be -#' exported (which enables to *restore* the full `Spectra` respectively -#' `MsExperiment` objects). #' -#' For an `MsExperiment` object, the exported files include: +#' The `storeResults()` and `loadResults()` methods with the `PlainTextParam` +#' option enable users to save/load an `MsExperiment` or `XcmsExperiment` +#' object as a collections of plain text files in/from a specified folder. This +#' folder, defined with the `path` parameter, will be created by the +#' `storeResults()` function. Any previous exports eventually present in that +#' folder will be overwritten. #' -#' - The [sampleData()] stored as a text file named *sample_data.txt*. +#' For an `MsExperiment` object, the exported files, stored into the directory +#' specifyied with the `path` parameter, include: #' -#' - The [fileNames()] of the *Spectra* object stored in a tabular format in a -#' text file named *spectra_files.txt*.The file names will only be exported if -#' the `Spectra` object uses a [MsBackendMzR()] backend. For other backends no -#' information on raw spectra data is currently exported with `PlainTextParam`. -#' -#' - Processing queue of the `Spectra` object, ensuring that any spectra data -#' modifications are retained. It is stored in a `json` file named -#' *spectra_processing_queue.json*. +#' - The [sampleData()] stored as a text file named *sample_data.txt*. #' #' For an `XcmsExperiment` object, the exported files are the same as those #' for an `MsExperiment` object, with the addition of the following: #' #' - The [processHistory()] information of the object, stored in a `json` file -#' named *process_history.json*. +#' named *process_history.json*. #' #' - The chromatographic peak information obtained with [chromPeaks()] and -#' [chromPeaksData()], stored in tabular format in the text files -#' *chrom_peaks.txt* and *chrom_peak_data.txt* respectively. +#' [chromPeaksData()], stored in tabular format in the text files +#' *chrom_peaks.txt* and *chrom_peak_data.txt* respectively. #' #' - The retention time information obtained with [adjustedRtime()] stored -#' in the text file named *rtime_adjusted.txt*. +#' in a text file named *rtime_adjusted.txt*. #' #' - The [featureDefinitions()] stored in a text file named -#' *feature_definitions.txt*. Additionally, a second file named -#' *feature_peak_index.txt* is generated to connect the features' definitions -#' with their names. +#' *feature_definitions.txt*. Additionally, a second file named +#' *feature_peak_index.txt* is generated to connect the features' definitions +#' with their names. +#' +#' For a `Spectra` object, the exported files include: +#' +#' - The `processingQueueVariables`, `processing`, [processingChunkSize()] and +#' `backend` class information of the object stored in a text file named +#' *spectra_slots.txt*. +#' +#' - The processing queue of the `Spectra` object, ensuring that any spectra +#' data modifications are retained. It is stored in a `json` file named +#' *spectra_processing_queue.json*. +#' +#' Import/export of the MS data depends on the respective implementation of +#' the respective `MsBackend` object. For `MsBackendMzR`, the exported data +#' and related text files are: +#' +#' - The backend's [spectraData()] stored in a tabular format in a text file +#' named *backend_data.txt*. #' -#' This `param` class and method are part of the possible dispatch of the -#' generic function `storeResults`. The folder will be created by calling -#' `storeResults`. If the folder already exists, previous exports in that -#' folder might get overwritten. +#' @note #' -#' @param path for `PlainTextParam` `character(1)`, defining where the files are -#' going to be stored. The default will be `tempdir()`. +#' The function relies on the `storeResults()` and `loadResults()` methods of +#' the [Spectra()] object and the used [MsBackend()] to store and restore the +#' MS data. These methods might not be available for all `MsBackend` +#' implementations. Also, it might be required to specify the path containing +#' the MS data files using the `spectraPath` parameter. +#' +#' @param path For `PlainTextParam()`: `character(1)`, defining where the files +#' are going to be stored/ should be loaded from. The default is +#' `path = tempdir()`. +#' +#' @param spectraPath For `loadResults()`: `character(1)` optionally allowing to +#' define the (absolute) path where the spectra files (*data storage files*) +#' can be found. This parameter is passed to the `loadResults()` method of +#' the [MsBackend()]. #' #' @inheritParams storeResults #' -#' @return for `PlainTextParam`: a `PlainTextParam` class. `storeResults` does +#' @return For `PlainTextParam`: a `PlainTextParam` class. `storeResults` does #' not return anything but saves the object to collections of different plain -#' text files to a folder. +#' text files to a folder. The `loadResults()` method returns the restored +#' data as an instance of the class specified with parameter `object`. #' -#' @author Philippine Louail, Johannes Rainer. +#' @author Philippine Louail #' #' @importFrom jsonlite serializeJSON write_json unserializeJSON read_json #' +#' @importFrom utils read.table write.table +#' +#' @importFrom MsExperiment MsExperiment readMsExperiment +#' +#' @importFrom MsCoreUtils common_path +#' +#' @importFrom Spectra processingChunkSize dropNaSpectraVariables Spectra MsBackendMzR +#' +#' @importFrom stats setNames +#' #' @examples +#' #' ## Load test data set of class `MsExperiment` #' library(MsExperiment) #' fls <- dir(system.file("sciex", package = "msdata"), full.names = TRUE) @@ -96,6 +125,9 @@ #' ## Save as a collection of plain text files #' storeResults(object = faahko_sub, param = param) #' +#' ## Load this saved dataset +#' faahko_load <- loadResults(object = XcmsExperiment(), param = param) +#' NULL #' @noRd @@ -118,48 +150,166 @@ PlainTextParam <- function(path = tempdir()) { new("PlainTextParam", path = path) } - +### methods #' @rdname PlainTextParam setMethod("storeResults", signature(object = "MsExperiment", param = "PlainTextParam"), function(object, param){ - dir.create(path = param@path, recursive = TRUE, showWarnings = TRUE) - .store_msexperiment(x = object, path = param@path) + dir.create(path = param@path, + recursive = TRUE, + showWarnings = FALSE) + write.table(as.data.frame(sampleData(object)), sep = "\t", + file = file.path(param@path, + "sample_data.txt")) + ## call export of individual other objects (not MsExperiment data) + storeResults(spectra(object), param) + ## at some point also chromatograms, etc. } ) +#' @rdname PlainTextParam +setMethod("storeResults", + signature(object = "XcmsExperiment", + param = "PlainTextParam"), + function(object, param) { + callNextMethod() + .store_xcmsexperiment(x = object, path = param@path) + } +) -#' @noRd -.store_msexperiment <- function(x, path = tempdir()) { - .export_sample_data(as.data.frame(sampleData(x)), - file.path(path, "sample_data.txt")) - .export_spectra_files(x, path = path) - .export_spectra_processing_queue(spectra(x), path = path) -} +#' @rdname PlainTextParam +setMethod("loadResults", + signature(object = "MsExperiment", + param = "PlainTextParam"), + function(object, param, spectraPath = character()) { + fl <- file.path(param@path, "sample_data.txt") + if (!file.exists(fl)) + stop("No 'sample_data.txt' file found in the provided path.") + sd <- read.table(fl, sep = "\t") + rownames(sd) <- NULL #read.table force numbering of rownames + s <- loadResults(Spectra(), param, spectraPath = spectraPath) + res <- MsExperiment(sampleData = sd, spectra = s) + validObject(res) + res + }) -#' Sample data -#' @noRd -.export_sample_data <- function(x, file = tempfile()) { - write.table(x, file = file) -} +#' @rdname PlainTextParam +setMethod("loadResults", + signature(object = "XcmsExperiment", + param = "PlainTextParam"), + function(object, param, spectraPath = character()) { + res <- callNextMethod() + res <- .load_xcmsexperiment(res, path = param@path) + validObject(res) + res + }) + +#' @rdname PlainTextParam +setMethod("storeResults", signature(object = "Spectra", + param = "PlainTextParam"), + function(object, param) { + dir.create(path = param@path, + recursive = TRUE, + showWarnings = FALSE) + if (!existsMethod("storeResults", c(class(object@backend)[1L], + "PlainTextParam"))) + stop("Can not store a 'Spectra' object with backend '", + class(object@backend)[1L], "'") + storeResults(object@backend, param = param) + .export_spectra_processing_queue(object, path = param@path) + .export_spectra_slots(object, path = param@path) + }) + +#' @rdname PlainTextParam +setMethod("loadResults", signature(object = "Spectra", + param = "PlainTextParam"), + function(object, param, spectraPath = character()) { + ## here i am NOT making a separate function for the slots + fl <- file.path(param@path, "spectra_slots.txt") + if (!file.exists(fl)) + stop("No 'spectra_slots.txt' file found in ", param@path) + fls <- readLines(fl) + var_names <- sub(" =.*", "", fls) + var_values <- sub(".* = ", "", fls) + variables <- setNames(var_values, var_names) + if (!existsMethod("loadResults", c(variables[["backend"]], + "PlainTextParam"))) + stop("Can not store a 'Spectra' object with backend '", + variables["backend"], "'") + b <- loadResults(object = do.call(what = variables[["backend"]], + args = list()), + param = param, spectraPath = spectraPath) + s <- Spectra(b) + s@processingQueueVariables <- unlist(strsplit(variables[["processingQueueVariables"]], + "|", fixed = TRUE)) + s@processing <- unlist(strsplit(variables[["processing"]], "|" , + fixed = TRUE)) + s@processingChunkSize <- as.numeric(variables[["processingChunkSize"]]) + fl <- file.path(param@path, "spectra_processing_queue.json") + if (file.exists(fl)) + s <- .import_spectra_processing_queue(s, file = fl) + s + }) -#' Spectra file +#' @rdname PlainTextParam +setMethod("storeResults", signature(object = "MsBackendMzR", + param = "PlainTextParam"), + function(object, param) { + dir.create(path = param@path, + recursive = TRUE, + showWarnings = FALSE) + object <- dropNaSpectraVariables(object) + fl <- file.path(param@path, "backend_data.txt") + if (file.exists(fl)) + warning("Overwriting already present 'backend_data.txt' file") + writeLines(paste0("# ", class(object)[1L]), con = fl) + suppressWarnings( + write.table(object@spectraData, + file = fl, sep = "\t", quote = FALSE, + append = TRUE, row.names = FALSE)) +}) + +#' @rdname PlainTextParam +setMethod("loadResults", signature(object = "MsBackendMzR", + param = "PlainTextParam"), + function(object, param, spectraPath = character()) { + b <- MsBackendMzR() + fl <- file.path(param@path, "backend_data.txt") + if (!file.exists(fl)) + stop("No 'backend_data.txt' file found in the provided path.") + data <- read.table(file = fl, sep = "\t", header = TRUE) + rownames(data) <- NULL + data <- DataFrame(data) + b@spectraData <- data + if (length(spectraPath) > 0) { + old <- common_path(dataStorage(b)) + ## if (nchar(old) > 0) + ## old <- paste0(old, "/") + dataStorage(b) <- sub(old, spectraPath, dataStorage(b)) + } + b +}) + +#' Spectra slots +#' @param x `Spectra` +#' #' @noRd -.export_spectra_files <- function(x, path = character()) { - s <- spectra(x) - if (!inherits(s@backend, "MsBackendMzR")) - warning("Spectra data will not be exported, backend need to be of ", - "class 'MsBackendMzR'") - else { - fls <- fileNames(x) - write.table(fls, file = file.path(path, "spectra_files.txt"), - row.names = FALSE, col.names = FALSE) - } +.export_spectra_slots <-function(x, path = character()){ + con <- file(file.path(path, "spectra_slots.txt"), open = "wt") + on.exit(close(con)) + pq <- x@processingQueueVariables + writeLines(paste0("processingQueueVariables = ", paste(pq, collapse = "|")), + con = con) + p <- x@processing + writeLines(paste0("processing = ", paste(p, collapse = "|")), con = con) + writeLines(paste0("processingChunkSize = ", processingChunkSize(x)), + con = con) + writeLines(paste0("backend = ", class(x@backend)[1L]), con = con) } #' Processing queue -#' @param x `Spectra` +#' @param x `Spectra` #' #' @noRd .export_spectra_processing_queue <- function(x, path = character()) { @@ -169,16 +319,11 @@ setMethod("storeResults", file.path(path, "spectra_processing_queue.json")) } - -#' @rdname PlainTextParam -setMethod("storeResults", - signature(object = "XcmsExperiment", - param = "PlainTextParam"), - function(object, param){ - callNextMethod() - .store_xcmsexperiment(x = object, path = param@path) - } -) +#' @noRd +.import_spectra_processing_queue <- function(x, file = character()) { + x@processingQueue <- unserializeJSON(read_json(file)[[1L]]) + x +} #' @noRd .store_xcmsexperiment <- function(x, path = tempdir()) { @@ -191,6 +336,25 @@ setMethod("storeResults", .export_features(x, path) } +#' @noRd +.load_xcmsexperiment <- function(x, path = character(), + spectraExport = logical()){ + x <- as(x, "XcmsExperiment") + fl <- file.path(path, "chrom_peaks.txt") + x <- .import_chrom_peaks(x, path) + fl <- file.path(path, "process_history.json") + if (file.exists(fl)) + x <- .import_process_history(x, fl) + else stop("No \"process_history.json\" file found in ", path) + fl <- file.path(path, "rtime_adjusted.txt") + if (file.exists(fl)) + x <- .import_adjusted_rtime(x, fl) + fl <- file.path(path, "feature_definitions.txt") + if (file.exists(fl)) + x <- .import_features(x, path) + x +} + #' Processing history #' @noRd .export_process_history <- function(x, path = character()) { @@ -198,19 +362,47 @@ setMethod("storeResults", write_json(serializeJSON(ph), file.path(path, "process_history.json")) } +#' @noRd +.import_process_history <- function(x, file = character()) { + ph <- unserializeJSON(read_json(file)[[1L]]) + x@processHistory <- ph + x +} + #' Chromatographic peaks #' @noRd .export_chrom_peaks <- function(x, path = character()) { - write.table(chromPeaks(x), file = file.path(path, "chrom_peaks.txt")) - write.table(as.data.frame(chromPeakData(x)), + write.table(chromPeaks(x), file = file.path(path, "chrom_peaks.txt"), + sep = "\t") + write.table(as.data.frame(chromPeakData(x)), sep = "\t", file = file.path(path, "chrom_peak_data.txt")) } +#' @noRd +.import_chrom_peaks <- function(x, path = character()) { + f <- file.path(path, "chrom_peaks.txt") + pk <- as.matrix(read.table(f, sep = "\t")) + f <- file.path(path, "chrom_peak_data.txt") + if (!file.exists(f)) + stop("No \"chrom_peak_data.txt\" file found in ", path) + pkd <- read.table(f, sep = "\t") + x@chromPeaks <- pk + x@chromPeakData <- pkd + x +} + #' Retention times #' @noRd .export_adjusted_rtime <- function(x, path = character()) { write.table(adjustedRtime(x), file = file.path(path, "rtime_adjusted.txt"), - row.names = FALSE, col.names = FALSE) + row.names = FALSE, col.names = FALSE, sep = "\t") +} + +#' @noRd +.import_adjusted_rtime <- function(x, file = character()) { + rts <- read.table(file, sep = "\t")[, 1L] + x@spectra$rtime_adjusted <- as.numeric(rts) + x } #' Features @@ -221,6 +413,21 @@ setMethod("storeResults", feature_index = rep(seq_len(nrow(fts)), lengths(fts$peakidx)), peak_index = unlist(fts$peakidx, use.names = FALSE)) fts$peakidx <- NA - write.table(fts, file = file.path(path, "feature_definitions.txt")) - write.table(pkidx, file = file.path(path, "feature_peak_index.txt")) + write.table(fts, file = file.path(path, "feature_definitions.txt"), + sep = "\t") + write.table(pkidx, file = file.path(path, "feature_peak_index.txt"), + sep = "\t") +} + +#' @noRd +.import_features <- function(x, path = character()) { + f <- file.path(path, "feature_definitions.txt") + fts <- read.table(f, sep = "\t") + f <- file.path(path, "feature_peak_index.txt") + if (!file.exists(f)) + stop("No \"feature_peak_index.txt\" file found in ", path) + pkidx <- read.table(f, sep = "\t") + fts$peakidx <- unname(split(pkidx$peak_index, pkidx$feature_index)) + x@featureDefinitions <- fts + x } diff --git a/R/RDataParam.R b/R/RDataParam.R index 59a7db86..84400ff4 100644 --- a/R/RDataParam.R +++ b/R/RDataParam.R @@ -1,24 +1,37 @@ -#' @title Store `XcmsExperiment` object as .RData file +#' @title Store/Load an `XcmsExperiment` object as/from .RData file #' #' @name RDataParam #' #' @export -#' -#' @family xcms result export formats. -#' +#' +#' @family xcms result export and import formats. +#' #' @description -#' The `RDataParam` class and method allow users to save an `XcmsExperiment` -#' object as an .RData file with a chosen filename. The object gets exported -#' using [`save()`] function. This `param` class and method are part of the -#' possible dispatch of the generic function `storeResults`. -#' +#' The `RDataParam` class and method allow users to save or load an +#' `XcmsExperiment` object as/from an .RData file with a defined filename. The +#' object gets exported using [`save()`] function and imported using the +#' [`load()`] function. This `param` class and method are part of the +#' possible dispatch of the generic functions `storeResults()` and +#' `loadResults()`. +#' #' @param fileName for `RDataParam` `character(1)`, defining the file name. The #' default will be `tempfile()`. -#' +#' +#' @param spectraPath for `loadResults` `character(1)`, defining the +#' absolute path where the spectra files should be imported from when loading +#' the object. The default will be set using the common file path of all the +#' spectra files when exporting. This is only supported if the backend of the +#' object loaded is `MsBackendMzr()` +#' #' @inheritParams storeResults -#' +#' +#' @inheritParams loadResults +#' +#' @importFrom Spectra dataStorageBasePath<- +#' #' @return for `RDataParam`: a `RDataParam` class. `storeResults` does not -#' return anything but saves the object to a RData file. +#' return anything but saves the object to a RData file. `loadResults` returns +#' an object of class `XcmsExperiment` #' #' @author Philippine Louail #' @@ -26,24 +39,27 @@ #' #' ## Load a test data set with detected peaks #' faahko_sub <- loadXcmsData("faahko_sub2") -#' -#' ## Define param +#' +#' ## Define param #' param <- RDataParam(fileName = "example_xcms_object") -#' +#' #' ## Save as RData #' storeResults(object = faahko_sub, param = param) -#' +#' +#' ## Load this saved dataset +#' xcmse <- loadResults(object = XcmsExperiment(), param = param) +#' NULL #' @noRd setClass("RDataParam", - slots = c(fileName = "character"), + slots = c(fileName = "character"), contains = "Param", prototype = prototype( fileName = character()), validity = function(object) { msg <- NULL - if (length(object@fileName) != 1) + if (length(object@fileName) != 1) msg <- c("'fileName' has to be a character string of length 1") msg }) @@ -54,13 +70,30 @@ setClass("RDataParam", RDataParam <- function(fileName = tempfile()) { new("RDataParam", fileName = fileName) } - + #' @rdname RDataParam setMethod("storeResults", - signature(object = "XcmsExperiment", - param = "RDataParam"), + signature(object = "XcmsExperiment", + param = "RDataParam"), function(object, param){ save(object, file = param@fileName) } ) +#' @rdname RDataParam +setMethod("loadResults", + signature(object = "XcmsExperiment", + param = "RDataParam"), + function(object, param, spectraPath = character()){ + env <- new.env() + load(file = param@fileName, envir = env) + res <- get(ls(env)[1], envir = env) + if (!length(spectraPath) == 0 && + inherits(spectra(res)@backend, "MsBackendMzR")) { + dataStorageBasePath(spectra(res)) <- spectraPath + } + + res + } +) + diff --git a/R/XcmsExperiment-functions.R b/R/XcmsExperiment-functions.R index e2b2957d..7117e8e3 100644 --- a/R/XcmsExperiment-functions.R +++ b/R/XcmsExperiment-functions.R @@ -1134,3 +1134,8 @@ featureArea <- function(object, mzmin = min, mzmax = max, rtmin = min, object@chromPeaks else chromPeaks(object@msFeatureData) } + +#' function to create an empty `XcmsExperiment` object +XcmsExperiment <- function() { + as(MsExperiment(), "XcmsExperiment") +} diff --git a/R/XcmsExperiment-plotting.R b/R/XcmsExperiment-plotting.R index ed16537b..32a6ef4f 100644 --- a/R/XcmsExperiment-plotting.R +++ b/R/XcmsExperiment-plotting.R @@ -437,6 +437,8 @@ setMethod( #' #' @importFrom grDevices n2mfrow #' +#' @importFrom Spectra filterEmptySpectra +#' #' @export #' #' @author Johannes Rainer diff --git a/R/XcmsExperiment.R b/R/XcmsExperiment.R index 356edbce..b540334b 100644 --- a/R/XcmsExperiment.R +++ b/R/XcmsExperiment.R @@ -1450,7 +1450,9 @@ setMethod("dropAdjustedRtime", "XcmsExperiment", function(object) { #' @rdname XcmsExperiment setMethod("hasAdjustedRtime", "MsExperiment", function(object) { - any(spectraVariables(spectra(object)) == "rtime_adjusted") + if (length(spectra(object))) + any(spectraVariables(spectra(object)) == "rtime_adjusted") + else FALSE }) #' @rdname XcmsExperiment diff --git a/man/PlainTextParam.Rd b/man/PlainTextParam.Rd index 8bd80648..ddef0371 100644 --- a/man/PlainTextParam.Rd +++ b/man/PlainTextParam.Rd @@ -4,6 +4,12 @@ \alias{PlainTextParam} \alias{storeResults,MsExperiment,PlainTextParam-method} \alias{storeResults,XcmsExperiment,PlainTextParam-method} +\alias{loadResults,MsExperiment,PlainTextParam-method} +\alias{loadResults,XcmsExperiment,PlainTextParam-method} +\alias{storeResults,Spectra,PlainTextParam-method} +\alias{loadResults,Spectra,PlainTextParam-method} +\alias{storeResults,MsBackendMzR,PlainTextParam-method} +\alias{loadResults,MsBackendMzR,PlainTextParam-method} \title{Store contents of `MsExperiment` and `XcmsExperiment` objects as plain text files} \usage{ @@ -12,10 +18,23 @@ PlainTextParam(path = tempdir()) \S4method{storeResults}{MsExperiment,PlainTextParam}(object, param) \S4method{storeResults}{XcmsExperiment,PlainTextParam}(object, param) + +\S4method{loadResults}{MsExperiment,PlainTextParam}(object, param, spectraPath = character()) + +\S4method{loadResults}{XcmsExperiment,PlainTextParam}(object, param, spectraPath = character()) + +\S4method{storeResults}{Spectra,PlainTextParam}(object, param) + +\S4method{loadResults}{Spectra,PlainTextParam}(object, param, spectraPath = character()) + +\S4method{storeResults}{MsBackendMzR,PlainTextParam}(object, param) + +\S4method{loadResults}{MsBackendMzR,PlainTextParam}(object, param, spectraPath = character()) } \arguments{ -\item{path}{for `PlainTextParam` `character(1)`, defining where the files are -going to be stored. The default will be `tempdir()`.} +\item{path}{For `PlainTextParam()`: `character(1)`, defining where the files +are going to be stored/ should be loaded from. The default is +`path = tempdir()`.} \item{object}{\code{MsExperiment} or \code{XcmsExperiment} The data object that needs to be saved.} @@ -23,59 +42,75 @@ to be saved.} \item{param}{The parameter object selecting and configuring the format for saving. It can be one of the following classes: \code{\link{RDataParam}}, \code{\link{PlainTextParam}}, or \code{MzTabMParam}.} + +\item{spectraPath}{For `loadResults()`: `character(1)` optionally allowing to +define the (absolute) path where the spectra files (*data storage files*) +can be found. This parameter is passed to the `loadResults()` method of +the [MsBackend()].} } \value{ -for `PlainTextParam`: a `PlainTextParam` class. `storeResults` does +For `PlainTextParam`: a `PlainTextParam` class. `storeResults` does not return anything but saves the object to collections of different plain -text files to a folder. +text files to a folder. The `loadResults()` method returns the restored +data as an instance of the class specified with parameter `object`. } \description{ -The `PlainTextParam` class and method enable users to save `MsExperiment` or -`XcmsExperiment` objects as collections of plain text files in a specified -folder. Note that, while for all xcms results within the `XcmsExperiment` can -and will be exported, the full raw MS data (of the object's `Spectra` object) -will currently not be exported in plain text format. For `Spectra` using the -[MsBackendMzR()] backend, the names of the raw data files will however be -exported (which enables to *restore* the full `Spectra` respectively -`MsExperiment` objects). +The `storeResults()` and `loadResults()` methods with the `PlainTextParam` +option enable users to save/load an `MsExperiment` or `XcmsExperiment` +object as a collections of plain text files in/from a specified folder. This +folder, defined with the `path` parameter, will be created by the +`storeResults()` function. Any previous exports eventually present in that +folder will be overwritten. -For an `MsExperiment` object, the exported files include: +For an `MsExperiment` object, the exported files, stored into the directory +specifyied with the `path` parameter, include: - The [sampleData()] stored as a text file named *sample_data.txt*. -- The [fileNames()] of the *Spectra* object stored in a tabular format in a -text file named *spectra_files.txt*.The file names will only be exported if -the `Spectra` object uses a [MsBackendMzR()] backend. For other backends no -information on raw spectra data is currently exported with `PlainTextParam`. - -- Processing queue of the `Spectra` object, ensuring that any spectra data -modifications are retained. It is stored in a `json` file named -*spectra_processing_queue.json*. - For an `XcmsExperiment` object, the exported files are the same as those for an `MsExperiment` object, with the addition of the following: - The [processHistory()] information of the object, stored in a `json` file -named *process_history.json*. + named *process_history.json*. - The chromatographic peak information obtained with [chromPeaks()] and -[chromPeaksData()], stored in tabular format in the text files -*chrom_peaks.txt* and *chrom_peak_data.txt* respectively. + [chromPeaksData()], stored in tabular format in the text files + *chrom_peaks.txt* and *chrom_peak_data.txt* respectively. - The retention time information obtained with [adjustedRtime()] stored -in the text file named *rtime_adjusted.txt*. + in a text file named *rtime_adjusted.txt*. - The [featureDefinitions()] stored in a text file named -*feature_definitions.txt*. Additionally, a second file named -*feature_peak_index.txt* is generated to connect the features' definitions -with their names. - -This `param` class and method are part of the possible dispatch of the -generic function `storeResults`. The folder will be created by calling -`storeResults`. If the folder already exists, previous exports in that -folder might get overwritten. + *feature_definitions.txt*. Additionally, a second file named + *feature_peak_index.txt* is generated to connect the features' definitions + with their names. + +For a `Spectra` object, the exported files include: + +- The `processingQueueVariables`, `processing`, [processingChunkSize()] and + `backend` class information of the object stored in a text file named + *spectra_slots.txt*. + +- The processing queue of the `Spectra` object, ensuring that any spectra + data modifications are retained. It is stored in a `json` file named + *spectra_processing_queue.json*. + +Import/export of the MS data depends on the respective implementation of +the respective `MsBackend` object. For `MsBackendMzR`, the exported data +and related text files are: + +- The backend's [spectraData()] stored in a tabular format in a text file + named *backend_data.txt*. +} +\note{ +The function relies on the `storeResults()` and `loadResults()` methods of +the [Spectra()] object and the used [MsBackend()] to store and restore the +MS data. These methods might not be available for all `MsBackend` +implementations. Also, it might be required to specify the path containing +the MS data files using the `spectraPath` parameter. } \examples{ + ## Load test data set of class `MsExperiment` library(MsExperiment) fls <- dir(system.file("sciex", package = "msdata"), full.names = TRUE) @@ -103,12 +138,15 @@ param <- PlainTextParam(path = pth) ## Save as a collection of plain text files storeResults(object = faahko_sub, param = param) +## Load this saved dataset +faahko_load <- loadResults(object = XcmsExperiment(), param = param) + } \seealso{ -Other xcms result export formats.: +Other xcms result export and import formats.: \code{\link{RDataParam}} } \author{ -Philippine Louail, Johannes Rainer. +Philippine Louail } -\concept{xcms result export formats.} +\concept{xcms result export and import formats.} diff --git a/man/RDataParam.Rd b/man/RDataParam.Rd index 617c3dc9..cd6aaf98 100644 --- a/man/RDataParam.Rd +++ b/man/RDataParam.Rd @@ -3,11 +3,14 @@ \name{RDataParam} \alias{RDataParam} \alias{storeResults,XcmsExperiment,RDataParam-method} -\title{Store `XcmsExperiment` object as .RData file} +\alias{loadResults,XcmsExperiment,RDataParam-method} +\title{Store/Load an `XcmsExperiment` object as/from .RData file} \usage{ RDataParam(fileName = tempfile()) \S4method{storeResults}{XcmsExperiment,RDataParam}(object, param) + +\S4method{loadResults}{XcmsExperiment,RDataParam}(object, param, spectraPath = character()) } \arguments{ \item{fileName}{for `RDataParam` `character(1)`, defining the file name. The @@ -19,34 +22,46 @@ to be saved.} \item{param}{The parameter object selecting and configuring the format for saving. It can be one of the following classes: \code{\link{RDataParam}}, \code{\link{PlainTextParam}}, or \code{MzTabMParam}.} + +\item{spectraPath}{for `loadResults` `character(1)`, defining the +absolute path where the spectra files should be imported from when loading +the object. The default will be set using the common file path of all the +spectra files when exporting. This is only supported if the backend of the +object loaded is `MsBackendMzr()`} } \value{ for `RDataParam`: a `RDataParam` class. `storeResults` does not -return anything but saves the object to a RData file. +return anything but saves the object to a RData file. `loadResults` returns +an object of class `XcmsExperiment` } \description{ -The `RDataParam` class and method allow users to save an `XcmsExperiment` -object as an .RData file with a chosen filename. The object gets exported -using [`save()`] function. This `param` class and method are part of the -possible dispatch of the generic function `storeResults`. +The `RDataParam` class and method allow users to save or load an +`XcmsExperiment` object as/from an .RData file with a defined filename. The +object gets exported using [`save()`] function and imported using the +[`load()`] function. This `param` class and method are part of the +possible dispatch of the generic functions `storeResults()` and +`loadResults()`. } \examples{ ## Load a test data set with detected peaks faahko_sub <- loadXcmsData("faahko_sub2") -## Define param +## Define param param <- RDataParam(fileName = "example_xcms_object") ## Save as RData storeResults(object = faahko_sub, param = param) +## Load this saved dataset +xcmse <- loadResults(object = XcmsExperiment(), param = param) + } \seealso{ -Other xcms result export formats.: +Other xcms result export and import formats.: \code{\link{PlainTextParam}} } \author{ Philippine Louail } -\concept{xcms result export formats.} +\concept{xcms result export and import formats.} diff --git a/man/XcmsExperiment.Rd b/man/XcmsExperiment.Rd index f7676365..793f3322 100644 --- a/man/XcmsExperiment.Rd +++ b/man/XcmsExperiment.Rd @@ -203,6 +203,8 @@ featureArea( features = character() ) +XcmsExperiment() + \S4method{plot}{MsExperiment,missing}(x, y, msLevel = 1L, peakCol = "#ff000060", ...) } \arguments{ diff --git a/man/loadResults.Rd b/man/loadResults.Rd new file mode 100644 index 00000000..2155cc1e --- /dev/null +++ b/man/loadResults.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/AllGenerics.R +\name{loadResults} +\alias{loadResults} +\title{Import various file format as XcmsExperiment object} +\usage{ +loadResults(object, param, ...) +} +\arguments{ +\item{object}{Define the class of the object to be imported. It can be one +of the following classes: \code{\link[=XcmsExperiment]{XcmsExperiment()}}, \code{\link[=MsExperiment]{MsExperiment()}} for now, +more class will be supported in the future.} + +\item{param}{The parameter object selecting and configuring the format for +saving. It can be one of the following classes: \code{\link{RDataParam}}, +\code{\link{PlainTextParam}}, or \code{MzTabParam}.} + +\item{...}{Optional parameters.} +} +\description{ +The \code{loadResults} function allows to import and create an \code{XcmsExperiment} +object from a file. Multiple formats for importing are available and can be +defined by the \code{param} argument. + +Supported \code{param} objects are: +\itemize{ +\item \code{\link{RDataParam}}: Import an \code{MsExperiment} or \code{XcmsExperiment} object from +an .RData file. +\item \code{\link{PlainTextParam}}: Import an \code{MsExperiment} or \code{XcmsExperiment} object +from a folder of text files. +\item \code{MzTabParam}: Load a MzTab-m file (to be defined). +} + +For specific examples, see the help pages of the individual parameter classes +listed above. +} +\note{ +The same \code{param} object can be used to import as it was used for export with +the \code{storeResults()} function. +} +\examples{ +## Load a test data set with detected peaks +faahko_sub <- loadXcmsData("faahko_sub2") + +## Save as RData +param <- RDataParam(fileName = "example_xcms_object") +storeResults(object = faahko_sub, param = param) + +## Load this saved dataset +xcmse <- loadResults(object = XcmsExperiment(),param = param) + +## Save as a collection of plain text files +pth = file.path(tempdir(), "test") +param <- PlainTextParam(path = pth) +storeResults(object = faahko_sub, param = param) + +## Load this saved dataset +faahko_load <- loadResults(object= XcmsExperiment(), param = param) + +} +\author{ +Philippine Louail +} diff --git a/tests/testthat/test_PlainTextParam.R b/tests/testthat/test_PlainTextParam.R index caaffe1c..17548145 100644 --- a/tests/testthat/test_PlainTextParam.R +++ b/tests/testthat/test_PlainTextParam.R @@ -1,29 +1,135 @@ xmse_full <- loadXcmsData("xmse") -test_that("storeResults,PlainTextParam,MsExperiment works", { +s <- spectra(xmse_full) +b <- s@backend + +test_that("storeResults,loadResults,PlainTextParam,MsBackendMzR works", { pth <- file.path(tempdir(), "test") param <- PlainTextParam(path = pth) + storeResults(b, param = param) + expect_true(dir.exists(pth)) + expect_true(file.exists(file.path(param@path, "backend_data.txt"))) + ## Loading data again + b2 <- loadResults(object = MsBackendMzR(), param) + expect_true(inherits(b2, "MsBackendMzR")) + b <- dropNaSpectraVariables(b) + expect_equal(b@spectraData, b2@spectraData) + expect_equal(peaksVariables(b), peaksVariables(b2)) + expect_equal(mz(b[1:20]), mz(b2[1:20])) + + ## Check the spectraPath parameter. + bp <- dataStorageBasePath(b) + ## manually change dataStorage path of backend + sd <- read.table(file.path(param@path, "backend_data.txt"), header = TRUE) + sd$dataStorage <- sub("faahKO", "other", sd$dataStorage) + write.table(sd, file = file.path(param@path, "backend_data.txt"), + sep = "\t", quote = FALSE, row.names = FALSE) + A <- loadResults(MsBackendMzR(), param) + expect_error(validObject(A), "invalid class") + A <- loadResults(MsBackendMzR(), param, spectraPath = bp) + expect_true(validObject(A)) + + param <- PlainTextParam(tempdir()) + expect_error(loadResults(MsBackendMzR(), param), "No 'backend_data") +}) + +test_that("storeResults,loadResults,PlainTextParam,Spectra works", { + pth <- file.path(tempdir(), "test1") + param <- PlainTextParam(path = pth) + ## add processingQueueVariables to test export + s@processingQueueVariables <- c(s@processingQueueVariables, "rtime") + s <- filterMzRange(s, c(200,300)) + s <- filterRt(s, c(3000, 3500)) # to ensure subsetted object would work + storeResults(s, param = param) + expect_true(dir.exists(pth)) + expect_true(file.exists(file.path(param@path, "backend_data.txt"))) + expect_true(file.exists(file.path(param@path, "spectra_slots.txt"))) + expect_true(file.exists(file.path(param@path, + "spectra_processing_queue.json"))) + ## Loading data again + s2 <- loadResults(object = Spectra(), param) + expect_true(inherits(s2, "Spectra")) + expect_true(inherits(s2@backend, "MsBackendMzR")) + s <- dropNaSpectraVariables(s) + expect_equal(length(s@processingQueue), length(s2@processingQueue)) + expect_equal(s@processingQueue[[1L]]@ARGS, s2@processingQueue[[1L]]@ARGS) + expect_equal(s@processingQueueVariables, s2@processingQueueVariables) + expect_equal(s@processing, s2@processing) + expect_equal(processingChunkSize(s), processingChunkSize(s2)) + expect_equal(s@backend@spectraData, s2@backend@spectraData) + expect_equal(rtime(s), rtime(s2)) + expect_equal(mz(s[1:10]), mz(s2[1:10])) # that does NOT work without calling functions directly with MsCoreUtils:: in Spectra. + expect_no_error(filterRt(s2, c(3000, 3500))) + + ## Check the spectraPath parameter. + ## Changing the path in the MsBackendMzR to simulate moving the exported data + bp <- dataStorageBasePath(s) + sd <- read.table(file.path(param@path, "backend_data.txt"), header = TRUE) + sd$dataStorage <- sub("faahKO", "other", sd$dataStorage) + write.table(sd, file = file.path(param@path, "backend_data.txt"), + sep = "\t", quote = FALSE, row.names = FALSE) + A <- loadResults(Spectra(), param) + expect_error(validObject(A@backend), "invalid class") + A <- loadResults(Spectra(), param, spectraPath = bp) + expect_true(validObject(A@backend)) + + param <- PlainTextParam(file.path(tempdir())) + expect_error(loadResults(Spectra(), param), "No 'spectra_slots") +}) + +test_that("storeResults,loadResults,PlainTextParam,MsExperiment works", { + pth <- file.path(tempdir(), "test3") + param <- PlainTextParam(path = pth) param2 <- PlainTextParam() expect_false(is.null(param2)) expect_error(new("PlainTextParam", path = c(tempdir(), tempdir()))) - mse <- filterMzRange(mse, c(200, 500)) - storeResults(mse, param = param) + tmp <- filterMzRange(mse, c(200, 500)) + tmp <- filterRt(tmp, c(3000, 3500)) + storeResults(tmp, param = param) expect_true(dir.exists(pth)) expect_true(file.exists(file.path(param@path, "sample_data.txt"))) - expect_true(file.exists(file.path(param@path, "spectra_files.txt"))) + expect_true(file.exists(file.path(param@path, "backend_data.txt"))) + expect_true(file.exists(file.path(param@path, "spectra_slots.txt"))) expect_true(file.exists(file.path(param@path, "spectra_processing_queue.json"))) + ## Loading data again + load_mse <- loadResults(object = MsExperiment(), param) + expect_true(inherits(load_mse, "MsExperiment")) + expect_equal(sampleData(tmp), sampleData(load_mse)) + a <- spectra(tmp) + b <- spectra(load_mse) + expect_equal(length(a@processingQueue), length(b@processingQueue)) + expect_equal(a@processingQueue[[1L]]@ARGS, b@processingQueue[[1L]]@ARGS) + expect_equal(rtime(a), rtime(b)) + expect_no_error(filterRt(load_mse, c(3000, 3500))) + + ## Check the spectraPath parameter. + bp <- dataStorageBasePath(tmp@spectra) + ## manually change dataStorage path of backend + sd <- read.table(file.path(param@path, "backend_data.txt"), header = TRUE) + sd$dataStorage <- sub("faahKO", "other", sd$dataStorage) + write.table(sd, file = file.path(param@path, "backend_data.txt"), + sep = "\t", quote = FALSE, row.names = FALSE) + A <- loadResults(MsExperiment(), param) + expect_error(validObject(spectra(A)@backend), "invalid class") + A <- loadResults(MsExperiment(), param, spectraPath = bp) + expect_true(validObject(spectra(A)@backend)) + + param <- PlainTextParam(tempdir()) + expect_error(loadResults(MsExperiment(), param), "No 'sample_data") }) -test_that("storeResults,PlainTextParam,XcmsExperiment works", { - pth = file.path(tempdir(), "test") +test_that("storeResults,loadResults,PlainTextParam,XcmsExperiment works", { + pth = file.path(tempdir(), "test4") param <- PlainTextParam(path = pth) param2 <- PlainTextParam() expect_false(is.null(param2)) - mse <- filterMzRange(xmse_full, c(200, 500)) - storeResults(xmse_full, param = param) + tmp <- filterMzRange(xmse_full, c(200, 500)) + tmp <- filterRt(tmp, c(3000, 4000)) + storeResults(tmp, param = param) expect_true(dir.exists(pth)) expect_true(file.exists(file.path(param@path, "sample_data.txt"))) - expect_true(file.exists(file.path(param@path, "spectra_files.txt"))) + expect_true(file.exists(file.path(param@path, "backend_data.txt"))) + expect_true(file.exists(file.path(param@path, "spectra_slots.txt"))) expect_true(file.exists(file.path(param@path, "spectra_processing_queue.json"))) expect_true(file.exists(file.path(param@path, "process_history.json"))) expect_true(file.exists(file.path(param@path, "chrom_peaks.txt"))) @@ -31,4 +137,39 @@ test_that("storeResults,PlainTextParam,XcmsExperiment works", { expect_true(file.exists(file.path(param@path, "rtime_adjusted.txt"))) expect_true(file.exists(file.path(param@path, "feature_definitions.txt"))) expect_true(file.exists(file.path(param@path, "feature_peak_index.txt"))) + + ## load data again + load_xmse <- loadResults(object = XcmsExperiment(), param) + expect_true(inherits(load_xmse, "XcmsExperiment")) + expect_equal(tmp@featureDefinitions, + load_xmse@featureDefinitions) + expect_equal(featureValues(tmp), featureValues(load_xmse)) + expect_equal(adjustedRtime(tmp), adjustedRtime(load_xmse)) + expect_no_error(filterRt(load_xmse, c(3000, 3500))) + expect_equal(tmp@chromPeaks, load_xmse@chromPeaks) + expect_equal(tmp@chromPeakData, load_xmse@chromPeakData) + expect_equal(tmp@sampleData, load_xmse@sampleData) + expect_equal(length(tmp@processHistory), length(load_xmse@processHistory)) + expect_equal(tmp@processHistory[[1L]], load_xmse@processHistory[[1L]]) + expect_equal(tmp@processHistory[[2L]], load_xmse@processHistory[[2L]]) + expect_equal(tmp@processHistory[[3L]], load_xmse@processHistory[[3L]]) + expect_equal(tmp@processHistory[[4L]], load_xmse@processHistory[[4L]]) + expect_equal(tmp@processHistory[[5L]], load_xmse@processHistory[[5L]]) + ## The 6th param object contains functions for which the comparison fails + ## because of the name/namespace mentioned. See e.g. + ## tmp@processHistory[[6]]@param load_xmse@processHistory[[6]]@param + + ## Check the spectraPath parameter. + bp <- dataStorageBasePath(tmp@spectra) + ## manually change dataStorage path of backend + sd <- read.table(file.path(param@path, "backend_data.txt"), header = TRUE) + sd$dataStorage <- sub("faahKO", "other", sd$dataStorage) + write.table(sd, file = file.path(param@path, "backend_data.txt"), + sep = "\t", quote = FALSE, row.names = FALSE) + expect_error(loadResults(XcmsExperiment(), param), "invalid class") + A <- loadResults(XcmsExperiment(), param, spectraPath = bp) + expect_true(validObject(spectra(A)@backend)) + + param <- PlainTextParam(tempdir()) + expect_error(loadResults(MsExperiment(), param), "No 'sample_data") }) diff --git a/tests/testthat/test_XcmsExperiment.R b/tests/testthat/test_XcmsExperiment.R index d538a762..dae693f1 100644 --- a/tests/testthat/test_XcmsExperiment.R +++ b/tests/testthat/test_XcmsExperiment.R @@ -1413,15 +1413,16 @@ test_that("setAs,XcmsExperiment,xcmsSet works", { expect_equal(peaks(res), chromPeaks(xmseg)) }) -test_that("storeResults,RDataParam works", { +test_that("storeResults,loadResults, RDataParam works", { param <- RDataParam(fileName = "test") param2 <- RDataParam() expect_false(is.null(param2)) storeResults(xmse, param = param) expect_true(file.exists("test")) - load("test") - expect_s4_class(object, "XcmsExperiment") - expect_equal(object, xmse) + res <- loadResults(object = XcmsExperiment(), param, + spectraPath = character()) #not sure how to test for spectraFilePath not empty + expect_s4_class(res, "XcmsExperiment") + expect_equal(res, xmse) }) test_that("fillChromPeaks,XcmsExperiment works with verboseBetaColumns", {