rickhelmus / patRoon

Workflow solutions for mass-spectrometry based non-target analysis.
https://rickhelmus.github.io/patRoon/
GNU General Public License v3.0
65 stars 19 forks source link

Filtering MS/MS Peaks with Characteristic Fragment Ions #95

Open Jasmin-Zeng opened 11 months ago

Jasmin-Zeng commented 11 months ago

Hello, I would like to ask if patRoon can filter MS/MS peaks containing one or more characteristic fragment ions (CFIs).

For example, I am analyzing organophosphate esters, and the MS/MS peaks of these compounds often include specific fragment ions like C18H16O4P+, C12H12O4P+, C6H8O4P+, H4O4P+, and H2O3P+. I now only want to retain mslists that contain one or more of the characteristic fragment ions, but I don't know how to achieve this.

I would be grateful if you could advise.

rickhelmus commented 10 months ago

Hi @Jasmin-Zeng ,

Sorry for my late reply.

This is definitely possible. There are various ways, but probably the easiest is to use the delete() function, for instance:

# function to compare mzs with some tolerance
equalMZ <- function(mz1, mz2) abs(mz1 - mz2) < 0.005

# delete all MS/MS spectra without at least one characteristic fragment
mslistsF <- delete(mslists, j = function(pl, grp, ana, type)
{
    if (type != "MSMS")
        return(FALSE) # only consider MS/MS peak lists
    return(!any(sapply(c(94.05239, 107.06016, 300.1234), equalMZ, pl$mz))) # delete if none of these characteristic m/z are present
})

Note that in this example you will need to calculate the exact m/z values for your fragments.

Feel free to ask more details if needed.

Thanks, Rick

Jasmin-Zeng commented 10 months ago

Thank you for your reply, I will test it and get back to you with the results then.

Jasmin-Zeng commented 10 months ago

Hi @rickhelmus , Thank you for your guidance. I successfully integrated the feature of CFIs into my code, and it's functioning well now.

However, I have another question. I used MS-Dial for deconvolution of data collected in DIA mode and exported the results in .msp format, where precursor ions are well-matched with their corresponding fragment ions.

My question is: can this .msp file be imported into patRoon to generate MSPeakLists, thereby facilitating the use of patRoon's workflow for formula and compound annotation? I've attached the .msp file for your reference. Msp_DIA_300_400.zip

Thank you for your assistance.

rickhelmus commented 10 months ago

Hi @Jasmin-Zeng ,

Great!

Unfortunately, importing peak lists is not yet supported (but planned for the next major release). However, with a bit of creativity and coding, perhaps you could perform the following:

  1. Generate the MS peak lists with patRoon, setting precursorMzWindow to NULL so that DIA spectra are handled properly.
  2. Import the MSP files with loadMSLibrary()
  3. Use the delete() function to clear-out any mass peaks that are not in the imported MSP data.

Thanks, Rick

Jasmin-Zeng commented 10 months ago

Ok, I will try it as you suggested, thank you very much.

Boris-Droz commented 2 months ago

Hi all, just to follow the discussion. Could we do mass difference between characteristic fragment ions filtering? In the same, field is it possible to do the MS2 spectra annotation using patRoon?

Thank you very much

rickhelmus commented 2 months ago

Hi @Boris-Droz ,

If you want to only keep MS/MS peaks that have a certain m/z difference, you could run something like this:

mslistsF <- delete(mslists, j = function(pl, grp, ana, t)
{
    # NOTE: get the precursor from the MS spectrum, as it may be absent in the MS/MS spectrum
    prec <- mslists[[grp]]$MS[precursor == TRUE]$mz 
    diffs <- pl$mz - prec
    return(abs(diffs - 70.1234) > 0.005)
})

In this example, all the peaks will be checked to have a difference of 70.1234 with a tolerance of 0.005 Da. Peaks that fall outside are removed.

You can then use mslistsF in a 'regular' annotation workflow (generateFormulas() / generateCompounds()).

Does this answer your question?

Thanks, Rick

Boris-Droz commented 2 months ago

Hi Rick, That fantastic. Thank you for the amazing support. I successfully integrate both aspect in my patroon worflow. Those two examples (include the one from Jasmin) are very useful for advance data processing. Maybe will be useful to put it a section in the Handbook about it. Just I guess in the code above is it return(abs(diffs - 70.1234) < 0.005) but not return(abs(diffs - 70.1234) > 0.005)

rickhelmus commented 2 months ago

Hi @Boris-Droz ,

Great to hear! :-) I agree it would be great to have more examples out there on data filtering in general, there is plenty of things that can be done with delete(), as.data.table(), filter() and subsetting.

As for your question: the return value of the function passed as the j parameter should return which data is to be deleted. So in my example all the data is deleted that does not have a m/z difference of ~70.

Boris-Droz commented 2 months ago

Hi Rick,

Ho sorry it was my fault. I did read carefully what you mention in your previous post.

Thank you again

Boris