levitsky / pyteomics

Pyteomics is a collection of lightweight and handy tools for Python that help to handle various sorts of proteomics data. Pyteomics provides a growing set of modules to facilitate the most common tasks in proteomics data analysis.
http://pyteomics.readthedocs.io
Apache License 2.0
105 stars 34 forks source link

mass calculation with negative charge #60

Closed mgleeming closed 2 years ago

mgleeming commented 2 years ago

Hi!

I've been using pyteomics for a while and it's great! Thanks a bunch!

I just noticed that attempting to calculate anion masses as below returns negative values. Is this the expected behavior? Not a big deal but I would have expected positive values so thought I'd mention it. This was with version 4.4.2.

All the best, Michael

>>> from pyteomics import mass
>>> mass.calculate_mass(formula = 'C6H12O6', ion_type='M', charge = -1)
-179.05611163543
>>> mass.calculate_mass(formula = 'C6H12O6', ion_type='M', charge = -2)
-89.02441758433001
levitsky commented 2 years ago

Hi Michael!

Thanks for your feedback! There are a few things I have to say about this:

  1. calculate_mass with charge returns an m/z value. Technically, I don't see an issue with the fact that it's negative (because the charge is) but I can see how this can be inconvenient if not expected (e.g. when trying to compare values).
  2. Currently the implementation just assumes that charge is carried by protons, so it adds a proton mass (times charge) to the mass before dividing it by charge.
  3. Since in your case the charge is negative, the proton mass is actually subtracted from the molecular mass, which produces a correct result in case of deprotonation and an incorrect result for all other possible ways of ionization. Does this align with your expectations?

If the value is correct and sign is the only issue, I can add a parameter (like absolute=True|False) that would control if the absolute value is returned. What do you think?

mgleeming commented 2 years ago

Thanks a lot! Yes that makes sense! Yes, the values are correct and it was just the sign that caught me out. An absolute=True parameter as you suggest would be great!

For you third point, yes I'd noticed this. The application here was a script that calculates lipid m/z values and compares to experimental data. Usually we work with +'ve ion data but this time got some negative ion data so I was trying to adapt some old code. For other ways of ionization (+Cl-, +HCOO- ... ) I'd just calculated a net mass shift from deprotonated masses and then added that to the pyteomics result. In other work, I'm frequently trying to calculate alternate cation ionisation products as well (M+Na etc...)

An enhancement that adds the ability to define ionisation type would be very useful for us and probably others.

Thanks again for a great package!

mobiusklein commented 2 years ago

Something like this would work for the implementation details for the conversion:

def neutral_mass(mz, z, charge_carrier=PROTON):
    return (mz * abs(z)) - (z * charge_carrier)

def mass_charge_ratio(neutral_mass, z, charge_carrier=PROTON):
    return (neutral_mass + (z * charge_carrier)) / abs(z)