Skip to content

Improve adduct/isotope generation - #319

Merged
joewandy merged 10 commits into
masterfrom
review-adduct-and-isotope-implementation
Jun 1, 2026
Merged

Improve adduct/isotope generation#319
joewandy merged 10 commits into
masterfrom
review-adduct-and-isotope-implementation

Conversation

@joewandy

@joewandy joewandy commented Jun 1, 2026

Copy link
Copy Markdown
Member

Summary

This PR improves simulated isotope envelopes, adduct generation, and deisotoping/deadducting support.

The main scientific change is replacing the previous carbon-only isotope approximation with a multi-element isotope envelope approximation based on natural isotope abundances. The PR also adds configurable adduct priors/profiles and concentration controls, removes adducts we cannot currently simulate correctly, and adds OpenMS / ms-deisotope helpers plus tests to validate generated patterns.

Scientific fixes and behavior changes

Isotope generation

Isotope generation now approximates the full-formula isotope envelope by convolving per-element natural isotope distributions (NATURAL_ISOTOPES).

  • Build each element distribution relative to its monoisotope.
  • Raise each element distribution to the element count via repeated convolution.
  • Merge/prune intermediate states with mass_precision, min_prob, and max_states to keep runtime bounded.
  • Keep peaks until total_proportion is reached.
  • max_peaks now defaults to unlimited; if explicitly set too low to reach total_proportion, a warning is emitted.
  • Always preserve the zero-shift monoisotopic peak as isotopes[0], because downstream code assumes that invariant.

Implementation lives in vimms/IsotopeDistribution.py, with vimms/Chemicals.py::Isotopes kept as the public wrapper.

Adduct generation

Adduct metadata now has one shared definition table in vimms/Common.py, from which names, priors, and mass terms are derived.

  • Adduct proportions are sampled from a Dirichlet distribution with configurable priors/profiles.
  • Default positive/negative adduct sets are derived from the shared table.
  • Custom adduct names are validated, including ionisation-mode compatibility.
  • The mislabeled potassium adduct M+2K+H was replaced with M+2K-H.
  • Negative-mode adduct coverage now includes M+Cl, M+FA-H, and M+Ac-H; M+Cl uses the chloride ion mass.
  • Unsupported dimer/multimer adducts (2M+H, 2M+NH4) were removed because the old mass-term approach applies isotope envelopes incorrectly for multimer species. It is better not to simulate them than to produce scientifically wrong isotope/adduct peaks.

Deisotoping and deadducting

vimms/Deisotoping.py is added with utilities for validating and processing generated isotope/adduct patterns.

  • A lightweight deisotoper is added and tested against multi-element isotope envelopes.
  • OpenMS and ms-deisotope helper paths are added and covered by tests.
  • OpenMS deadducting support is implemented with focused helper functions for feature-map setup, adduct parsing, probability normalization, and neutral-mass reconstruction.
  • pyopenms and ms-deisotope are added as required dependencies for this PR's functionality and tests.

Validation

Added tests/test_deisotoping.py to cover:

  • multi-element isotope envelope generation,
  • monoisotope preservation under filtering,
  • warning behavior when max_peaks truncates the requested envelope,
  • removal/rejection of unsupported dimer adducts,
  • potassium replacement and chloride adduct definitions,
  • adduct metadata consistency from the shared table,
  • polarity-aware adduct validation,
  • OpenMS and ms-deisotope helper behavior,
  • end-to-end deadducting examples.

Local validation run in the vimms conda environment:

  • pytest tests/test_deisotoping.py -q -> 30 passed
  • pytest tests/test_chemical_generation.py tests/test_controllers_TopN.py -q -> 31 passed
  • pytest -q -> 144 passed, 2 existing warnings
  • Smoke simulation: generated HMDB-derived chemicals, isotope/adduct envelopes, and non-empty Top-N MS1/MS2 scans.

CI is currently green on the PR.

Limitations

  • True dimer/multimer adduct isotope envelopes are not supported in this PR. They were removed rather than approximated incorrectly.
  • The adduct prior defaults are heuristic and configurable; they are not claimed to be empirically calibrated for all instruments or sample classes.
  • Unknown chemicals remain single-peak representations. This is intentional because ROI-derived unknowns may already represent a specific isotope/adduct peak or noise, and expanding them could invent correlated signal.

@joewandy
joewandy merged commit 0d8a694 into master Jun 1, 2026
6 checks passed
@joewandy
joewandy deleted the review-adduct-and-isotope-implementation branch June 1, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant