# Subformula Enumeration

> Use when when performing chemical noise removal on MS/MS spectra and you need to validate whether each fragment ion m/z is consistent with loss of a subformula from the precursor ion.

- Skill: `holobiomicslab/subformula-enumeration` (Agent Skill)
- Install (CLI): `npx skillmds@latest add holobiomicslab/subformula-enumeration`
- Raw SKILL.md: https://api.skillmd.com/api/skills/holobiomicslab/subformula-enumeration/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: CC-BY-4.0
- Author: HolobiomicsLab (https://skillmd.com/u/holobiomicslab)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/holobiomicslab/subformula-enumeration

---


# subformula-enumeration

## Summary

Enumerate all chemically plausible subformulas that can be lost from a molecular precursor ion to form observed fragment ions in MS/MS spectra. This supports formula-based noise filtering by checking whether each detected peak could arise from a valid neutral loss.

## When to use

When performing chemical noise removal on MS/MS spectra and you need to validate whether each fragment ion m/z is consistent with loss of a subformula from the precursor ion. Use this when you have a SMILES string or molecular formula and precursor m/z, and want to reject ions that cannot be explained by any plausible neutral loss.

## When NOT to use

- When the precursor ion structure is unknown or no SMILES/formula is available; subformula enumeration requires molecular structure input.
- When performing electronic denoising only (ions with identical intensities ≥4 occurrences); use electronic_denoising instead.
- When the observed spectrum contains no fragment ions or only the precursor ion; subformula-based validation cannot filter a spectrum with negligible fragmentation.

## Inputs

- SMILES string or molecular formula (master formula)
- Adduct type (e.g., '[M+H]+', '[M+Na]+')
- Observed fragment ion m/z values from MS/MS spectrum
- Precursor m/z
- Spectrum intensity array (numpy array with m/z and intensity columns)

## Outputs

- List of valid subformula losses (neutral losses) from precursor
- Denoise tags (valid/noise classification) for each fragment ion
- Filtered spectrum with only ions matching valid subformula losses
- Denoised spectrum (numpy array with retained m/z and intensity)

## How to apply

First, extract the master formula from the SMILES string and adduct type using prep_formula, which adjusts the formula based on adduct ionization state. Next, compute precursor ion mass statistics using get_pmz_statistics to establish reference mass values. Then populate all possible subformulas from the master formula using get_all_subformulas, which generates candidate neutral losses. For each observed fragment ion m/z, call check_candidates to determine if any subformula loss can explain the ion within mass tolerance; the algorithm computes the expected m/z of the fragment if that subformula were lost and compares it against the observed m/z. Finally, tag ions as valid or noise using get_denoise_tag based on whether at least one chemically plausible subformula loss matches the observed fragment. Retain only ions tagged as valid.

## Related tools

- **RDkit** (Extract molecular structure information and compute molecular mass from SMILES strings) — https://www.rdkit.org/
- **molmass** (Calculate exact masses for molecular formulas and subformula losses)
- **chemparse** (Parse and manipulate chemical formulas for loss calculations)
- **spectral_denoising** (Package containing prep_formula, get_pmz_statistics, get_all_subformulas, check_candidates, and get_denoise_tag functions) — https://github.com/FanzhouKong/spectral_denoising
- **numpy** (Handle spectrum arrays and mass/intensity data structures)

## Examples

```
peak = np.array([[79.02, 521.0], [81.01, 659.0]], dtype=np.float32); smiles = 'O=c1nc[nH]c2nc[nH]c12'; adduct = '[M+Na]+'; peak_denoised = sd.spectral_denoising(peak, smiles, adduct)
```

## Evaluation signals

- All retained fragment ions have at least one chemically plausible subformula loss that matches within mass tolerance; compute expected m/z = precursor_mz - loss_mass and verify |observed_mz - expected_mz| ≤ tolerance.
- Entropy similarity between denoised spectrum and reference/ground-truth spectrum is higher than entropy similarity of the raw noisy spectrum and the reference (entropy_similarity should increase after denoising).
- No fragment ions with identical m/z appear multiple times after denoising (if they did, they may be artifacts).
- The number of retained ions is substantially fewer than the input spectrum (confirming that chemical noise was removed), but the denoised spectrum retains the major diagnostic peaks.
- All removed ions either cannot be explained by any subformula loss or have no corresponding entry in the enumerated subformula list.

## Limitations

- Subformula enumeration assumes 100% accuracy of the input SMILES string or molecular formula; errors in chemical structure will propagate to incorrect subformula predictions.
- The method relies on a predefined mass tolerance for matching observed m/z to expected fragment m/z; the tolerance must be calibrated to the instrument's mass accuracy (e.g., ±5 ppm for Orbitrap).
- Complex molecules with many atoms generate exponentially many subformulas; enumeration may become computationally expensive for large precursor ions.
- The algorithm does not account for multi-step losses or rearrangements; fragment ions formed via complex fragmentation pathways may be incorrectly tagged as noise.
- Adduct type must be specified correctly; incorrect adduct assignment (e.g., '[M+H]+' vs '[M+Na]+') will produce incorrect precursor m/z and invalidate all downstream subformula checks.

## Evidence

- [other] Step2: Populate all possible subformulas from master formula: "Step2: Populate all possible subformulas from master formula using get_all_subformulas"
- [other] For any given fragment ion, the algorithm will try to find a plausible subformula loss: "For any given fragment ion, the algorithm will try to find a plausible subformula loss that could form this ion (function ``check_cnadidates``)"
- [other] The ``formula_denoising`` function removes chemical noise ions in MS/MS spectra by evaluating if it could be formed from a chemically plausible subformula loss: "The ``formula_denoising`` function removes chemical noise ions in MS/MS spectra by evaluating if it could be formed from a chemically plausible subformula loss"
- [other] Apply formula_denoising by extracting the master formula from SMILES and adduct using prep_formula, computing precursor ion statistics with get_pmz_statistics, populating all possible subformulas from the master formula using get_all_subformulas, checking each fragment ion against candidate subformula losses using check_candidates, and tagging ions as valid or noise using get_denoise_tag.: "Apply formula_denoising by: (a) extracting the master formula from SMILES and adduct using prep_formula, (b) computing precursor ion statistics with get_pmz_statistics, (c) populating all possible"
- [other] Step 0: Modify the master formula based on SMILES and adduct information: "Step 0: Modify the master formula based on SMILES and adduct information"

