---
title: "Description and usage of MobilityTransformR"
package: "`r BiocStyle::pkg_ver('MobilityTransformR')`"
date: "`r BiocStyle::doc_date()`"
author: 
- name: Liesa Salzer
  affiliation: Analytical BioGeoChemistry, Helmholtz Zentrum München
  email: liesa.salzer@helmholtz-munich.de
  
vignette: >
    %\VignetteIndexEntry{Description and usage of MobilityTransformR}
    %\VignetteEngine{knitr::rmarkdown}
    %\VignetteEncoding{UTF-8}
    %\VignettePackage{MobilityTransformR}
    %\VignetteDepends{MobilityTransformR,xcms,BiocStyle,msdata}
output:
    BiocStyle::html_document:
        toc_float: true    
bibliography: references.bib
csl: biomed-central.csl
---

```{r style, echo = FALSE, results = 'asis', message=FALSE}
BiocStyle::markdown()
```

```{r, echo = FALSE, message = FALSE}
library(BiocStyle)
```

# Introduction

Capillary elecrophoresis coupled to mass spectrometry (CE-MS) in fields as 
proteomics or metabolomics is less common than for example liquid 
chromatography-mass spectrometry (LC-MS). A reason might be less reproducible 
migration times (MT) compared to retention times (RT) because of fluctuations 
in the Electroosmotic flow (EOF). 

However, the effective mobility $µ_{eff}$ of a compound remains stable in the 
same electrophoretic system. The use of an effective mobility scale instead 
of a migration time scale circumvents the drawback of MT shifts and will 
result in highly reproducible peaks, which has already been shown in 2001 
@Schmitt-Kopplin2001. 

Effective mobility transformation for CE-MS data is not as straightforward as 
in CE-UV and until now and to our knowledge there is no implementation in R 
that performs effective mobility transformation of CE-MS(/MS) data. 

As a model for the `MobilityTransformR` package, we have taken 
the recently developed open-source ROMANCE software @ROMANCE2018, which 
transforms the MT scale of CE-MS data into an $µ_{eff}$ scale. However, 
the outputs are two separate files, each for positive and negative 
mobilities. 
We developed the `MobilityTransformR` package to perform  mobility 
transformation of CE-MS/MS data in the R environment. Also, different 
to ROMANCE, the output will be a single file containing both, the positive 
and negative effective mobilities. 

The transformation is performed using functionality from the packages 
`r BiocStyle::Biocpkg("MetaboCoreUtils")`, `r BiocStyle::Biocpkg("xcms")`,
`r BiocStyle::Biocpkg("MSnbase")`, and `r BiocStyle::Biocpkg("Spectra")`.
The transformed data can be exported as `.mzML` file and can be further 
analyzed in R or other software.

The CE-MS test data are from the `r BiocStyle::Biocpkg("msdata")` package.


# Setup

## Installation
The `MobilityTransformR` package can be installed as follows: 

```{r, eval = FALSE}
if (!requireNamespace("BiocManager", quietly = TRUE)) {
    install.packages("BiocManager")
}

BiocManager::install("MobilityTransformR")
```

To show the different functionality of `MobilityTransformR`, we
need also to load the packages `xcms` and `Spectra`.
If you have not installed them yet, type

```{r, eval = FALSE}
if (!requireNamespace("BiocManager", quietly = TRUE)) {
    install.packages("BiocManager")
}

BiocManager::install("xcms")
BiocManager::install("Spectra")
```
into the Console.

## Load required libries
`MobilityTransformR` integrates functions from different 
libraries.

```{r libraries, message=FALSE, warning=FALSE}
# load required libraries
library(MobilityTransformR)
library(xcms)
library(Spectra)
```


## Load test data

To showcase the functionality of the `MobilityTransformR` 
package two CE-MS test sets containing a mixtures of different metabolites 
at a concentration of 10 ppm and 25 ppm precisely, acquired at positive 
CE polarity and positive ionization mode is used and imported from the 
`msdata`package. 
Paracetamol was added to the analysis as EOF marker in a final 
concentration of 50 ppm to the sample. Procaine was added as 
positively charged, secondary marker at a 
final concentration of 10 ppm. 
The markers are required for the later effective mobility transformation 
process. 
The test data is loaded using the `readMSData()` function from 
`MSnbase`.

```{r data, message=FALSE}
fl <- dir(system.file("CE-MS", package = "msdata"), 
          full.names = TRUE)

# Load mzXML data with MSnBase
raw_data <- readMSData(files = fl, mode = "onDisk")
```

# Get Marker Migration Times
In order to perform the effective mobility transformation, first the 
migration times (MTs) of the markers needs to be determined. If multiple 
files are used, the MT of the markers in each file must be determined since 
they will vary based on EOF fluctuations. 

The `getMtime()` function requires an `OnDiskMSnExp` object,`raw_data`, as 
input and uses an mz-range `mz` and MT-range `mt` to generate an Extracted 
Ion Electropherogram (EIE). The MT of the peak will be determined by 
`findChromPeaks` from 
`xcms`.
It is very important to define the `mz`-range and 
`mt`-range as narrow as possible to ensure that the right peak will 
be picked. The mz-tolerance defining the `mz`-range depends on the 
mass accuracy of the mass spectrometer that was used to acquire the data.

## Get MT of EOF Marker Paracetamol
In order to check the right `mz`-, and `mt`-window for the exact MT 
determination, we use the`plot(chromatogram())` function to plot the 
respective EIE. 

Note that the plot functions are adapted from LC-MS package `MSnbase`, 
which has "retention time" as default x-axis label. 

```{r EOF marker, message=FALSE, warning=FALSE}
# mz tolerance depends on MS mass accuracy
tolerance <- 0.005

# [M+H]+ of paracetamol: mz = 152.071154
mz_paracetamol <- c(152.071154 - tolerance, 152.071154 + tolerance)
mt_paracetamol <- c(600, 900)

marker_EIE <- raw_data |>
    filterMz(mz = mz_paracetamol) |>
    filterRt(rt = mt_paracetamol)

plot(chromatogram(marker_EIE),
    main = "Paracetamol EIE",
    xlab = "migration time (sec)"
)

# adjust mz and MT windows if necessary
```

Use the adapted values to get the exact MT of Paracetamol. 
If several files will be used it is important to select a `mt`-range 
wide enough to get the right Paracetamol-peaks in all files, because single 
migration times might change significantly due to EOF-fluctuations between 
measurements. 

```{r EOF marker getMT, message=FALSE, warning=FALSE}
# get the MT of paracetamol
paracetamol <- getMtime(raw_data,
    mz = mz_paracetamol,
    mt = mt_paracetamol
)
paracetamol
```

## MT of Secondary Marker Procaine
Effective mobilities can be already calculated using the EOF marker 
Paracetamol. However, it is also possible to calculate the mobility using a 
secondary marker. This might be of interest for example when the peak 
shape of the main marker is not sufficient or ambiguity detection.

In order to show how we can use a secondary marker to convert the data, we 
create in the next step a data.frame containing the MT and file information 
from another, secondary marker called Procaine.

```{r charged marker, message=FALSE, warning=FALSE}
procaine <- data.frame(
    "rtime" = c(450.239, 465.711),
    "fileIdx" = c(1, 2)
)
```


# Effective mobility scale transformation
`mobilityTransform` uses different functions to perform the effective
mobility transformation depending on the input type. It is possible to 
convert `numeric`, `Spectra`, and `OnDiskMSnExp`. 
Here, we show how each input-class can be transformed.

## Effective mobility transformation of single migration times

Effective mobility scale transformation is performed either using a single or 
two mobility markers. Functions were adapted from González-Ruiz et al. 
@ROMANCE2018 . 
The standard equation to calculate effective mobility $µ_{eff}$ is 

\begin{equation}
      µ_{eff} = \frac{l}{E} (\frac{1}{t_M - (t_R/2)} - 
      \frac{1}{t_{EOF} - (t_R/2)}) 
  (\#eq:mobility1)
\end{equation}

with $t_M$ the migration time that is transformed, $t_{EOF}$ the MT of the 
EOF marker and optional $t_R$ which is the time of the electrical field ramp.

If the peak shape of the EOF marker is bad or it cannot be detected for other 
reasons, the effective mobility might also be calculated using a secondary 
mobility marker with known mobility: 

\begin{equation}
      µ_{eff} = µ_A + \frac{l}{E} (\frac{1}{t_M - (t_R/2)} - 
      \frac{1}{t_A - (t_R/2)}) 
  (\#eq:mobility2)
\end{equation}
with $t_A$, the MT of the secondary marker and its corresponding mobility 
$µ_A$. 

Last, the mobility might be calculated using both markers. Therefore, there 
is no need to know the applied electrical field nor the exact capillary 
length. 

\begin{equation}
      µ_{eff} = µ_A \frac{t_M - t_{EOF}}{t_A - t_{EOF}} * 
      \frac{t_A - (t_R/2)}{t_M - (t_R/2)} 
  (\#eq:mobility3)
\end{equation}


## Calculation of the Secondary Marker Mobility $µ_A$ 
First, a `data.frame` is created that stores the marker information, 
that will be used to transform the data. Either one or two markers can be 
used for the transformation. The `data.frame` needs at least the columns
`rtime` and `mobility`. Additional columns to store marker 
information might be added as well.
Here, we start with the neutral EOF marker Paracetamol, having the effective 
mobility of 0 $\frac{mm^2}{kV*min}$.

```{r, message=FALSE}
# Create a data.frame that stores marker information
marker <- paracetamol
marker$markerID <- "Paracetamol"
marker$mobility <- 0
```


Then the effective mobility of the secondary mobility marker Procaine, as 
single migration time, is determined according to eq. \@ref(eq:mobility1).
The transformation is performed using the marker information from 
Paracetamol. 
Moreover, if only a single marker is provided for the transformation, also 
the applied voltage `U` in kV, and the total and effective capillary 
length `L` in mm is needed. 
Additionally the field ramping time `tR` (in min) can be included for
corrections. 

```{r mobility, message=FALSE}
procaineMobility <- mobilityTransform(
    x = procaine[1, 1], marker = marker[1, ],
    tR = 3 / 60, U = +30, L = 800
)
procaineMobility
```

Note: The unit of the mobility is $\frac{mm^2}{kV*min}$

## Effective mobility transformation of whole CE-MS runs

`mobilityTransform` can also be applied to whole CE-MS runs stored 
either as `Spectra`-object or `OnDiskMSnExp`-object.
As shown as before, either a single or two markers can be used for 
conversion. 
Here, we add the marker information of Procaine to the marker 
`data.frame`, so the transformation will be done on both markers 
according to eq. \@ref(eq:mobility3).

```{r, message=FALSE}
procaine$markerID <- "Procaine"
procaine$mobility <- procaineMobility
marker <- rbind(marker, procaine)
```


### Effective mobility transformation of OnDiskMSnExp objects
The migration time scale of `raw_data2` is transformed, returning the 
same class.

```{r, message=FALSE}
# Conversion of mt in OnDiskMSnExp objects
mobility_data <- mobilityTransform(x = raw_data, marker = marker)

# OnDiskMSnExp can by exported by writeMSData, Note that it is important to
# set copy = FALSE, (otherwise spectrum ordering will be wrong)
fl_mobility_data <- tempfile()
writeMSData(filterFile(mobility_data, 1),
    file = fl_mobility_data, copy = FALSE
)
```


### Effective mobility transformation of Spectra objects
`Spectra`-objects can be transformed similarly in 
`mobilityTransform`. 
The resulting `Spectra`-objects can then also be exported as 
`.mzML` for further processing in different software.
```{r, message=FALSE}
# load the test data as spectra object
spectra_data <- Spectra(fl[1], backend = MsBackendMzR())

spectra_mobility <- mobilityTransform(
    spectra_data,
    marker[marker$fileIdx == 1, ]
)


# Transformed data can then be exported again as .mzML file to use in xcms or
# other software
fl_mobility <- tempfile()
export(spectra_mobility, MsBackendMzR(), file = fl_mobility)
```


# Inspect and Analyze the Transformed Data 
The transformed data can displayed and further analyzed with  e.g. 
`xcms`. Note that the effective mobility can be accessed by e.g. 
`spectra_mobility$rtime`, since functions where adapted from LC-MS 
based `rformassspectrometry` functions.
The resulting unit of the effective mobility is $\frac{mm^2}{kV*min}$.

Here, we inspect them with the `plot(chromatogram())` function from 
`xcms`. 

As described before, the test data contain different metabolites in 10 ppm 
and 25 ppm final concentration, acquired in positive ionization mode. We can 
check the effective mobilities of single compounds by extracting their EIE as 
for example Lysine (mz = 147.112806).


```{r mobility transformed data, message=FALSE}
# Example: Extract ion electropherogram (EIE) from lysine
mz_lysine <- c(147.112806 - tolerance, 147.112806 + tolerance)
mobilityRestriction <- c(1000, 2500)

# Extract ion electropherogram of compound
lysine_EIE <- mobility_data |>
    filterMz(mz = mz_lysine) |>
    filterRt(rt = mobilityRestriction)

plot(chromatogram(lysine_EIE),
    main = expression(paste("Lysine EIE - µ"[eff], " scale")),
    xlab = expression(paste("µ"[eff], "  (", frac("mm"^2, "kV min"), ")"))
)

# compare with extracted ion electropherogram of migration time scale
lysine_mt_EIE <- raw_data |>
    filterMz(mz = mz_lysine) |>
    filterRt(c(400, 600))

plot(chromatogram(lysine_mt_EIE),
    main = "Lysine EIE - MT scale",
    xlab = "MT (sec)"
)
```


# Session information

```{r si}
sessionInfo()
```


# References
