--- title: "Minifying files with RaMS" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Minifying-files-with-RaMS} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} options(rmarkdown.html_vignette.check_title = FALSE) options(tidyverse.quiet = TRUE) data.table::setDTthreads(2) knitr::opts_chunk$set( collapse = TRUE, comment = "#>", out.width = "80%", fig.align = 'center', fig.height = 3, fig.width = 6.5 ) ``` As of version 1.1.0, `RaMS` also has functions that allow irrelevant data to be removed from the file to reduce file sizes. Like `grabMSdata`, there's one wrapper function `minifyMSdata` that accepts mzML or mzXML files, plus a vector of *m/z* values that should either be kept (`mz_include`) or removed (`mz_exclude`). The function then opens up the provided MS files and removes data points in the MS^1^ and MS^2^ spectra that fall outside the accepted bounds. `mz_include` is useful when only a few masses are of interest, as in targeted metabolomics. `mz_exclude` is useful when many masses are known to be contaminants or interfere with peakpicking/plotting abilities. This minification can shrink a file over three orders of magnitude, decreasing both processing time and memory allocation later in the pipeline. This is also very useful for creating demo MS files - `RaMS` uses these functions to produce the sample data in `extdata`, with 6 MS files taking up less than 5 megabytes of disk space. Many other programs provide the ability to shrink files, but none (known to me) shrink files by excluding *m/z* values and instead can only remove certain retention times. Below, we begin with a large MS file containing both MS^1^ and MS^2^ data and extract only the data corresponding to valine/glycine betaine and homarine. ```{r minifyfile, results='hide'} library(RaMS) msdata_files <- list.files( system.file("extdata", package = "RaMS"), full.names = TRUE, pattern = "mzML" )[1:4] initial_filename <- msdata_files[1] output_filename <- gsub(x=paste0("minified_", basename(initial_filename)), "\\.gz", "") masses_of_interest <- c(118.0865, 138.0555) minifyMSdata(files = initial_filename, output_files = output_filename, mz_include = masses_of_interest, ppm = 10, warn = FALSE) ``` Then, when we open the file up (with `RaMS` or other software) we are left with the data corresponding only to those compounds: ```{r opendata, results='hide'} init_msdata <- grabMSdata(initial_filename) msdata <- grabMSdata(output_filename) ``` ```{r showmini} knitr::kable(head(msdata$MS1, 3)) knitr::kable(head(msdata$MS2, 3)) ``` Both the TIC and BPC are updated to reflect the smaller file size as well: ```{r TICBPCdiffs} par(mfrow=c(2, 1), mar=c(2.1, 2.1, 1.1, 0.1)) plot(init_msdata$BPC$rt, init_msdata$BPC$int, type = "l", main = "Initial BPC") plot(msdata$BPC$rt, msdata$BPC$int, type = "l", main = "New BPC") ``` ```{r cleanmini, include=FALSE} layout(1) unlink(output_filename) ``` *** The `minifyMSdata` function is vectorized so the exact same syntax can be used for multiple files: ```{r vectorizedmini} dir.create("mini_mzMLs/") output_files <- paste0("mini_mzMLs/", basename(msdata_files)) output_files <- gsub(x=output_files, "\\.gz", "") minifyMSdata(files = msdata_files, output_files = output_files, verbosity = 0, mz_include = masses_of_interest, ppm = 10, warn = FALSE) ``` ```{r ggplotmini, fig.height=2} mini_msdata <- grabMSdata(output_files, verbosity = 0) library(ggplot2) ggplot(mini_msdata$BPC) + geom_line(aes(x=rt, y=int, color=filename)) + theme_bw() ``` These new files are valid according to the validator provided in MSnbase, which means that most programs should be able to open them, but this feature is still experimental and may break on quirky data. If that happens, please feel free to submit a bug report at https://github.com/wkumler/RaMS/issues. ```{r cleanminimulti, include=FALSE} unlink("mini_mzMLs", recursive = TRUE) ``` *** As an example of how I use this minification function, here's the code used to create the minified files in the `\extdata` folder that ships with the package. This was especially useful because the package can't be more than 5MB but it's incredibly useful to include some standalone MS data for demos and vignettes like this one. I don't actually run this code in the vignette itself to save compilation time but it will run if you test it yourself. These files originate from the [Ingalls Lab](https://sites.google.com/view/anitra-ingalls) at the University of Washington, USA and are published in the manuscript [**"Metabolic consequences of cobalamin scarcity in diatoms as revealed through metabolomics"**](https://doi.org/10.1016/j.protis.2019.05.004). Files are downloaded from the corresponding [Metabolights repository](https://www.ebi.ac.uk/metabolights/MTBLS703/files). First, we identify the *m/z* values we'd like to keep in the minified files. For the demo data, I'll use the Ingalls Lab list of targeted compounds - those we have authentic standards for. ```{r mzs to include, eval=FALSE} raw_stans <- read.csv(paste0("https://raw.githubusercontent.com/", "IngallsLabUW/Ingalls_Standards/", "b098927ea0089b6e7a31e1758e7c7eaad5408535/", "Ingalls_Lab_Standards_NEW.csv")) mzs_to_include <- as.numeric(unique(raw_stans[raw_stans$Fraction1=="HILICPos",]$m.z)) # Include glycine betaine isotopes for README demo mzs_to_include <- c(mzs_to_include, 119.0899, 119.0835) ``` Then, we download the raw MS data from the online repository into which it's been deposited. ```{r download from MBLs, eval=FALSE} if(!dir.exists("vignettes/data"))dir.create("vignettes/data") base_url <- "ftp://ftp.ebi.ac.uk/pub/databases/metabolights/studies/public/MTBLS703/FILES/" chosen_files <- paste0(base_url, "170223_Smp_LB12HL_", c("AB", "CD", "EF"), "_pos.mzXML") new_names <- gsub(x=basename(chosen_files), "170223_Smp_", "") mapply(download.file, chosen_files, paste0("vignettes/data/", new_names), mode = "wb", method = "libcurl") ``` For MSMS data, we can also demo pulling data from MetabolomicsWorkbench: ```{r download from MW, eval=FALSE} MW_url <- paste0( "https://www.metabolomicsworkbench.org/data/file_extract_7z.php?", "A=ST002830_rawdata.zip&F=TCR_081023_Fu_WorkBench%252FS30657.mzXML" ) download.file(MW_url, destfile = "vignettes/data/S30657.mzXML") ``` Then we can actually perform the minification: ```{r minify, warning=FALSE, eval=FALSE} library(RaMS) if(!dir.exists("inst/extdata"))dir.create("inst/extdata", recursive = TRUE) init_files <- list.files("vignettes/data/", full.names = TRUE) out_files <- paste0("inst/extdata/", basename(init_files)) minifyMSdata(files = init_files, output_files = out_files, warn = FALSE, mz_include = mzs_to_include, ppm = 20) ``` Now we have four minified mzXML files in our inst/extdata folder. However, we'd like to be able to demo the mzML functionality as well as that of mzXMLs, so we can use [Proteowizard's](https://proteowizard.sourceforge.io/tools/msconvert.html) `msconvert` tool because `RaMS` can't convert between mzML and mzXML or vice versa. You'll need to install `msconvert` and add it to your path for this step. We also use `msconvert` to trim the files by retention time, keeping data between 4 and 15 minutes. Finally, we gzip the files to get them as small as possible, also using `msconvert`. ```{r msconvertchunk, eval=FALSE} system("msconvert inst/extdata/*.mzXML -o inst/extdata/temp --noindex") system("msconvert --mzXML inst/extdata/*.mzXML -o inst/extdata/temp --noindex") system('msconvert inst/extdata/temp/*.mzML --filter \"scanTime [240,900]\" -o inst/extdata -g') system('msconvert inst/extdata/temp/*.mzXML --mzXML --filter \"scanTime [240,900]\" -o inst/extdata -g') ``` And then for the last few steps, we again rename the files (since `msconvert` expands them to their full .raw names) and remove the ones we don't need for the demos. ```{r renameremove, eval=FALSE} init_files <- list.files("inst/extdata", full.names = TRUE) new_names <- paste0("inst/extdata/", gsub(x=init_files, ".*(Smp_|Extracts_)", "")) file.rename(init_files, new_names) unlink("inst/extdata/temp", recursive = TRUE) file.remove(list.files("inst/extdata", pattern = "mzXML$", full.names = TRUE)) file.remove(paste0("inst/extdata/", c("LB12HL_CD.mzXML.gz", "LB12HL_EF.mzXML.gz"))) ``` To check that the new files look ok, we can see if we can read them with `RaMS` and `MSnbase`. ```{r checkquality, eval=FALSE} MSnbase::readMSData(list.files("inst/extdata", full.names = TRUE)[1], msLevel. = 1) RaMS::grabMSdata(new_names[1]) ``` Finally, remember to clean up the original downloads folder ```{r vigdata cleanup, eval=FALSE} unlink("vignettes/data", recursive = TRUE) ``` *** README last built on `r Sys.Date()`