rformassspectrometry / Spectra

Low level infrastructure to handle MS spectra
https://rformassspectrometry.github.io/Spectra/
34 stars 24 forks source link

Efficient way to calculate neutral losses #181

Closed jorainer closed 3 years ago

jorainer commented 3 years ago

Goal: subtract the precursor m/z values from all m/z values of a Spectra. Problem: addProcessing does not work as the precursor m/z is not passed to the peaks matrix processing functions.

Possible solutions:

jorainer commented 3 years ago

An ad-hoc possibility to do that is by replacing the m/z values like in the example below:

df <- DataFrame(msLevel = c(1L, 2L, 2L, 2L), precursorMz = c(NA, 13, 12.2, 15),
                rtime = c(1, 2, 3, 4))
df$mz <- list(c(1:6), c(20, 24, 54), c(17, 200, 220, 221),
              c(123, 134, 135, 139))
df$intensity <- list(c(123, 343, 232, 45, 31, 532), c(5, 123, 99),
                     c(4324, 33499, 12, 5), c(151, 546, 1315, 24))
sps <- Spectra(df)

## Ensure any cached operations are applied:
sps <- applyProcessing(sps)
ms2 <- msLevel(sps) == 2L
mz(sps@backend)[ms2] <- mz(sps)[ms2] - precursorMz(sps)[ms2]

At present we have to call mz(sps@backend) because the mz<- is not (yet) implemented for Spectra. As a result we get then:

> mz(sps)
NumericList of length 4
[[1]] 1 2 3 4 5 6
[[2]] 7 11 41
[[3]] 4.8 187.8 207.8 208.8
[[4]] 108 119 120 124

the m/z of the MS 1 spectrum were not changed while we subtracted the precursor m/z from each MS2 spectrum.

Note: this only works for backends that support replacing m/z and intensity values (such as the MsBackendDataFrame).

I will still think of a version that would allow such operations to be applied independently of the backend type.

michaelwitting commented 3 years ago

Thank you very much. That helps. Any issues with the order of the mz values or is mz(sps@backend) taking care of this?

jorainer commented 3 years ago

mz(sps@backend) has to take care of that. this depends on how the backend is implemented. For our backends it is guaranteed. So the code above has to work correctly.

michaelwitting commented 3 years ago

Great, I would need this for some MS2 spectra, which are handled as MsBackendDataFrame. So everything should be fine. I will test with some data I have.

jorainer commented 3 years ago

We still will need to fix negative m/z values here.

michaelwitting commented 3 years ago

Filter everything out that is higher than the precursor and then make absolute values from the rest? Peaks above the precursor are anyway useless for this type of analysis.

jorainer commented 3 years ago

Wait - what exactly are you supposed to calculate here, m/z - precursor m/z or precursor m/z - m/z?

michaelwitting commented 3 years ago

Makes no difference. Normally, neutral losses are negative, but nobody uses it this way. People talk of NL 183 or NL 18.

jorainer commented 3 years ago

Can close this now. There is an example for neutral loss calculation in the vignette.