find-mfs: Accurate mass ➜ Molecular Formulae
find-mfs is a simple Python package for finding
molecular formulae candidates which fit some given mass (+/- an error window).
It implements Böcker & Lipták's algorithm for efficient formula finding, as used in
SIRIUS.
find-mfs also implements other methods
for filtering the MF candidate lists:
- Octet rule
- Ring/double bond equivalents (RDBE's)
- Predicted isotope envelopes, generated using Łącki and Startek's algorithm
as implemented in
IsoSpecPy - Bayesian candidate ranking, scoring formula plausibility using a database (COCONUT pre-bundled)
Motivation:
I needed to perform mass decomposition and, shockingly, I could not find a Python library for it
(despite being a routine process). find-mfs is intended to be used by anyone looking to incorporate
molecular formula finding into their Python project.
Installation
pip install find-mfs
Example Usage:
Simple queries
# For simple queries, one can use this convenience function
from find_mfs import find_chnops
find_chnops(
mass=613.2391, # Novobiocin [M+H]+ ion; C31H37N2O11+
charge=1, # Charge should be specified - electron mass matters
error_ppm=5.0, # Can also specify error_da instead
# --- FORMULA FILTERS ----
check_octet=True, # Candidates must obey the octet rule
filter_rdbe=(0, 20), # Candidates must have 0 to 20 ring/double-bond equivalents
max_counts='C*H*N*O*P0S2' # Element constraints: unlimited C/H/N/O,
# No phosphorous atoms, up to two sulfurs.
)
Output:
FormulaSearchResults(query_mass=613.2391, n_results=38)
Formula Error (ppm) Error (Da) RDBE
----------------------------------------------------------------------
[C6H25N30O4S]+ -0.12 0.000073 9.5
[C31H37N2O11]+ 0.14 0.000086 14.5
[C14H29N24OS2]+ 0.18 0.000110 12.5
[C16H41N10O11S2]+ 0.20 0.000121 1.5
[C29H33N12S2]+ -0.64 0.000392 19.5
... and 33 more
Batch Queries
# If processing many masses, it's better to instantiate a FormulaFinder object
from find_mfs import FormulaFinder
finder = FormulaFinder()
finder.find_formulae(
mass=613.2391, # Novobiocin [M+H]+ ion; C31H37N2O11+
charge=1,
error_ppm=5.0,
# ... etc
)
Including Isotope Envelope Information
If an isotope envelope is available, the candidate list can be dramatically reduced.
import numpy as np
# STEP 1: Retrieve isotope envelope from experimental data
observed_envelope = np.array(
[ # m/z , relative intsy.
[613.2397, 1.00],
[614.2429, 0.35],
[615.2456, 0.10],
]
)
# STEP 2: define isotope matching parameters
from find_mfs import IsotopeMatchConfig
iso_config = IsotopeMatchConfig(
envelope=observed_envelope, # np.ndarray with an m/z column and an intensity column
mz_tolerance_da=0.1, # Tolerance for aligning isotope signals. Should be very generous. Can also use mz_tolerance_ppm
minimum_rmse=0.05, # Default is 0.05, i.e. instrument reproduces isotope envelope w/ 5% fidelity
)
# STEP 3: include isotope matching parameters when performing a search
from find_mfs import FormulaFinder
finder = FormulaFinder()
finder.find_formulae(
mass=613.2391, # Novobiocin [M+H]+ ion; C31H37N2O11+
charge=1, # Charge should be specified - electron mass matters
error_ppm=3.0, # Can also specify error_da instead
# --- FORMULA FILTERS ----
check_octet=True, # Candidates must obey the octet rule
filter_rdbe=(0, 20), # Candidates must have 0 to 20 ring/double-bond equivalents
max_counts={
'P': 0, # Candidates must not have any phosophorous atoms
'S': 2, # Candidates can have up to two sulfur atoms
},
isotope_match=iso_config,
)
Output:
FormulaSearchResults(query_mass=613.2391, n_results=5)
Formula Error (ppm) Error (Da) RDBE Iso. Matches Iso. RMSE
------------------------------------------------------------------------------------------------------
[C31H37N2O11]+ 0.14 0.000086 14.5 3/3 0.0121
[C23H41N4O13S]+ -0.92 0.000565 5.5 3/3 0.0478
[C24H37N8O9S]+ 1.26 0.000772 10.5 3/3 0.0311
[C32H33N6O7]+ 2.32 0.001424 19.5 3/3 0.0230
[C25H33N12O5S]+ 3.44 0.002110 15.5 3/3 0.0146
Ranking Candidates by Plausibility
Even after filtering, the candidate list often includes chemically unintuitive
MF candidates. This package includes a method for scoring formula plausiblity.
This is done in the form of a Bayesian prior - a Gaussian Mixture Model. By default,
find-mfs bundles a GMM trained on the COCONUT
natural-products database.
The prior can be combined with mass error (and isotope RMSE, if available) to re-rank formula candidates by the overall best fit.
from find_mfs import FormulaFinder, FormulaPrior
finder = FormulaFinder()
results = finder.find_formulae(
mass=613.2391, charge=1, error_ppm=5.0,
check_octet=True, filter_rdbe=(0, 20),
max_counts='C*H*N*O*P0S2',
)
# Score with the bundled COCONUT-trained prior, then rank by posterior
prior = FormulaPrior.default() # no corpus or fitting needed
prior.score_results(
results,
mass_sigma_ppm=2.0, # Expected mass error of instrument
isotope_sigma=0.05, # Expected isotope fidelity of instrument (5%)
)
ranked = results.sort_by_posterior()
print(ranked.to_table())
Output:
Formula Error (ppm) Error (Da) RDBE Prior
-------------------------------------------------------------------------------
[C31H37N2O11]+ 0.14 0.000086 14.5 33.49
[C32H33N6O7]+ 2.32 0.001424 19.5 31.59
[C27H33N8O9]+ -4.24 -0.002599 15.5 31.58
[C32H41N2O6S2]+ 1.56 0.000956 13.5 18.75
[C19H41N4O18]+ 3.16 0.001937 1.5 18.71
... and 18 more
The true formula (novobiocin, C31H37N2O11) now ranks first.
Want a prior tuned to your own chemistry? Train one on any corpus of formula strings with
FormulaPrior().fit(my_formulae). Usesort_by_prior()to rank by the prior alone, ignoring mass error.
Jupyter Notebook:
See this Jupyter notebook for more thorough examples/demonstrations
If you use this package, make sure to cite:
- Böcker & Lipták, 2007 - this package uses their algorithm for formula finding...
- ...as implemented in SIRIUS: Böcker et. al., 2008
- Łącki, Valkenborg & Startek 2020 - this package uses IsoSpecPy to quickly simulate isotope envelopes
- Gohlke, 2025 - this package uses
molmass, which provides very convenient methods for handling chemical formulae
Contributing
Contributions are welcome. Here's a list of features I feel should be implemented eventually. The bold items are what I'm currently working on.
Statistics-based isotope envelope fittingFragmentation constraintsBayesian formula candidate ranking- Spectrum parsing (in progress)
- Element ratio constraints
- GUI app
License
This project is distributed under the GPL-3 license.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file find_mfs-0.4.0.tar.gz.
File metadata
- Download URL: find_mfs-0.4.0.tar.gz
- Upload date:
- Size: 853.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac8779a60f96ffc58649565528b158075025723d0529beb0a62972cee32ad993
|
|
| MD5 |
237e42d0e0919ccb4d7cc29b13b282b5
|
|
| BLAKE2b-256 |
f303b9049489fcde6e2cf419fe022aa648f876a1312fbe23bcccc50e4133672d
|