Matchms
Purpose and Scope
Matchms is a Python package for importing, cleaning, processing, and comparing
tandem mass spectra. This skill targets matchms 0.33.1, released 2026-06-08,
and corrects several breaking API changes that older tutorials do not reflect.
Use matchms for:
- MS/MS library search and query-versus-reference scoring
- Metadata harmonization, adduct/precursor handling, and peak filtering
- Cosine, modified-cosine, neutral-loss, approximate, and entropy scoring
- Structured score matrices, top-hit extraction, and spectral networks
- MGF, MSP, mzML, mzXML, JSON, mzSpecLib, and metabolomics-USI workflows
Do not use matchms as a replacement for:
- LC-MS feature detection, chromatographic alignment, peptide identification, or
protein quantification — use pyopenms
- Vendor raw-file conversion — convert to mzML/mzXML first
- A validated compound-identification protocol — similarity is evidence, not
proof of identity
Install the Verified Release
Create or activate an environment, then install the release used by this skill:
uv pip install "matchms==0.33.1"
Verify the runtime:
uv run python -c "import matchms; print(matchms.__version__)"
Matchms 0.33.1 supports Python 3.10-3.14 and installs RDKit as a regular
dependency. The old matchms[chemistry] extra is not part of the current
package metadata.
Operating Workflow
- Inspect the inputs. Record format, spectrum count, MS level, precursor
coverage, ion mode, peak counts, and identifier fields.
- Load with metadata harmonization enabled unless preserving source keys is
a deliberate requirement.
- Apply the same peak-processing steps to query and reference spectra.
Keep metadata enrichment separate when reference annotations are richer.
- Drop invalid spectra explicitly. Many
require_* filters return None.
- Choose the score from the scientific question, not from convenience.
Modified and neutral-loss scores require valid
precursor_mz.
- Estimate
len(references) * len(queries) before scoring. A sparse result
container does not automatically avoid computing every requested pair.
- Report score settings and evidence. Include tolerance, preprocessing,
score name, number of matched peaks when available, and candidate metadata.
- Validate top hits visually and chemically. Use mirror plots, precursor
agreement, ion/adduct compatibility, and orthogonal evidence.
Current API Guardrails
These points prevent the most common failures from pre-0.33 examples:
- Use
ModifiedCosineGreedy or ModifiedCosineHungarian; ModifiedCosine was
removed in 0.32.0.
- Do not call
add_losses(). It was removed in 0.27.0; use
spectrum.losses, spectrum.compute_losses(...), or
NeutralLossesCosine directly.
SpectrumProcessor is not callable. Use process_spectrum() or
process_spectra().
process_spectra() returns (processed_spectra, processing_report).
Scores.scores is a StackedSparseArray, often with separate structured
fields such as CosineGreedy_score and CosineGreedy_matches.
scores_by_query() returns (reference_spectrum, score_record) pairs, not
reference indices.
- Prefer
spectra in parameter names. The legacy spelling spectrums is
deprecated.
- Never load pickle files from an untrusted source; unpickling can execute code.
See references/migration.md for a complete old-to-current mapping.
Quick Start: Clean and Search a Library
from matchms import SpectrumProcessor, calculate_scores
from matchms.filtering import (
default_filters,
normalize_intensities,
require_minimum_number_of_peaks,
select_by_relative_intensity,
)
from matchms.importing import load_spectra
from matchms.similarity import ModifiedCosineGreedy
def load_and_process(path):
spectra = [default_filters(spectrum) for spectrum in load_spectra(path)]
processor = SpectrumProcessor(
[
normalize_intensities,
(select_by_relative_intensity, {"intensity_from": 0.01}),
(require_minimum_number_of_peaks, {"n_required": 5}),
]
)
processed, _ = processor.process_spectra(
spectra,
progress_bar=False,
create_report=False,
)
return processed
references = load_and_process("library.msp")
queries = load_and_process("queries.mgf")
metric = ModifiedCosineGreedy(tolerance=0.02)
scores = calculate_scores(
references=references,
queries=queries,
similarity_function=metric,
)
score_name = "ModifiedCosineGreedy_score"
matches_name = "ModifiedCosineGreedy_matches"
for query in queries:
ranked = scores.scores_by_query(query, name=score_name, sort=True)
for reference, values in ranked[:5]:
print(
query.get("spectrum_id", query.get("id")),
reference.get("compound_name", reference.get("spectrum_id")),
float(values[score_name]),
int(values[matches_name]),
)
SpectrumProcessor automatically orders built-in filters according to matchms's
filter order. The aggregate default_filters callable is not in that registry,
so run it first as above or expand its nine component filters. Inspect
processor.processing_steps and preserve it with results.
Pair Scoring
Similarity classes expose pair() for one reference/query pair. Cosine-family
results are structured NumPy scalars:
from matchms.similarity import CosineGreedy
result = CosineGreedy(tolerance=0.02).pair(reference, query)
similarity = float(result["score"])
matched_peaks = int(result["matches"])
Use calculate_scores() for matrix-oriented methods such as
FlashSimilarity; its single-pair path is supported but intentionally not the
optimized path.
Choose a Similarity Method
CosineGreedy — standard peak cosine with greedy peak assignment.
CosineHungarian — exact assignment; slower, useful for benchmarks.
CosineLinear — current linear-scaling cosine implementation.
ModifiedCosineGreedy — permits precursor-delta-shifted matches; common for
analog search.
ModifiedCosineHungarian — exact modified-cosine assignment.
NeutralLossesCosine — compares losses computed from precursor and fragments.
BlinkCosine — fast BLINK-style cosine approximation for larger matrices.
FlashSimilarity — optimized matrix scoring using spectral entropy or cosine
with fragment, neutral-loss, or hybrid matching.
BinnedEmbeddingSimilarity — binned spectral vectors and optional approximate
nearest-neighbor indexing.
PrecursorMzMatch, ParentMassMatch, MetadataMatch — candidate masks or
metadata constraints, not rich spectral scores.
FingerprintSimilarity — molecular-structure similarity; it is not spectral
similarity and requires fingerprints prepared from valid structures.
Read references/similarity.md before choosing a fast method, combining scores,
or interpreting structured outputs.
Large Comparisons
For all-vs-all scoring of one collection, set is_symmetric=True:
scores = calculate_scores(
references=spectra,
queries=spectra,
similarity_function=CosineGreedy(tolerance=0.02),
array_type="sparse",
is_symmetric=True,
)
For a precursor-gated search, compute and filter PrecursorMzMatch first, then
calculate the spectral metric only on retained coordinates through Pipeline
or Scores.calculate(...). See references/workflows.md.
Do not choose a universal "identification threshold." Score distributions
depend on preprocessing, mass accuracy, collision conditions, library quality,
and metric. At minimum, retain both score and matched-peak count for
cosine-family methods.
Bundled Library-Search CLI
scripts/library_search.py provides a reproducible query-versus-library search
with current score extraction, pair-count limits, preprocessing, and CSV output:
uv run python scripts/library_search.py \
queries.mgf library.msp hits.csv \
--metric modified \
--tolerance 0.02 \
--top-k 10 \
--min-score 0.6 \
--min-matches 5
Run --help for fast metrics, preprocessing options, identifier fields,
overwrite control, and the explicit large-matrix override.
Spectrum Objects and Visualization
import numpy as np
from matchms import Spectrum
spectrum = Spectrum(
mz=np.array([100.0, 150.0, 200.0]),
intensities=np.array([0.2, 1.0, 0.4]),
metadata={"spectrum_id": "query-1", "precursor_mz": 250.5},
)
print(spectrum.peaks.mz)
print(spectrum.get("precursor_mz"))
losses = spectrum.compute_losses(loss_mz_from=5.0, loss_mz_to=200.0)
spectrum.plot()
spectrum.plot_against(reference_spectrum)
References
Read only the reference needed for the task:
references/importing_exporting.md — formats, return types, generic I/O,
mzSpecLib, score serialization, and pickle safety
references/filtering.md — current filter catalog, clone/None semantics,
default filters, ordering, and SpectrumProcessor
references/similarity.md — all current similarity classes, outputs,
candidate masking, performance, and interpretation
references/workflows.md — library search, sparse gating, Pipeline, networks,
plotting, and provenance
references/migration.md — breaking changes and deprecated APIs
references/sources.md — authoritative docs, release notes, user guides, and
scientific publications used for this refresh
Non-Negotiable Checks
- Never compare raw queries against differently processed references.
- Never use modified or neutral-loss scoring without valid precursor metadata.
- Never assume a
Scores value is a plain float; inspect score_names.
- Never treat a high similarity score alone as confirmed identification.
- Never deserialize untrusted pickle data.
- Never launch an unbounded all-pairs comparison without estimating pair count.
1---
2name: matchms
3description: Process, clean, compare, and search tandem mass spectra with matchms. Use for MS/MS file I/O, metadata harmonization, peak filtering, spectral similarity, library matching, score matrices, and molecular-similarity networks. Use pyopenms instead for LC-MS feature detection or proteomics pipelines.
4allowed-tools: Read Write Edit Bash
5license: Apache-2.0
6compatibility: Requires Python >=3.10,<3.15, uv, and matchms 0.33.1. Local file workflows need no credentials; metabolomics-USI loading requires network access.
7metadata:
8 version: "2.0"
9 skill-author: K-Dense Inc.
10---
11
12# Matchms
13
14## Purpose and Scope
15
16Matchms is a Python package for importing, cleaning, processing, and comparing
17tandem mass spectra. This skill targets **matchms 0.33.1**, released 2026-06-08,
18and corrects several breaking API changes that older tutorials do not reflect.
19
20Use matchms for:
21
22- MS/MS library search and query-versus-reference scoring
23- Metadata harmonization, adduct/precursor handling, and peak filtering
24- Cosine, modified-cosine, neutral-loss, approximate, and entropy scoring
25- Structured score matrices, top-hit extraction, and spectral networks
26- MGF, MSP, mzML, mzXML, JSON, mzSpecLib, and metabolomics-USI workflows
27
28Do not use matchms as a replacement for:
29
30- LC-MS feature detection, chromatographic alignment, peptide identification, or
31 protein quantification — use pyopenms
32- Vendor raw-file conversion — convert to mzML/mzXML first
33- A validated compound-identification protocol — similarity is evidence, not
34 proof of identity
35
36## Install the Verified Release
37
38Create or activate an environment, then install the release used by this skill:
39
40```bash
41uv pip install "matchms==0.33.1"
42```
43
44Verify the runtime:
45
46```bash
47uv run python -c "import matchms; print(matchms.__version__)"
48```
49
50Matchms 0.33.1 supports Python 3.10-3.14 and installs RDKit as a regular
51dependency. The old `matchms[chemistry]` extra is not part of the current
52package metadata.
53
54## Operating Workflow
55
561. **Inspect the inputs.** Record format, spectrum count, MS level, precursor
57 coverage, ion mode, peak counts, and identifier fields.
582. **Load with metadata harmonization enabled** unless preserving source keys is
59 a deliberate requirement.
603. **Apply the same peak-processing steps** to query and reference spectra.
61 Keep metadata enrichment separate when reference annotations are richer.
624. **Drop invalid spectra explicitly.** Many `require_*` filters return `None`.
635. **Choose the score from the scientific question**, not from convenience.
64 Modified and neutral-loss scores require valid `precursor_mz`.
656. **Estimate `len(references) * len(queries)` before scoring.** A sparse result
66 container does not automatically avoid computing every requested pair.
677. **Report score settings and evidence.** Include tolerance, preprocessing,
68 score name, number of matched peaks when available, and candidate metadata.
698. **Validate top hits visually and chemically.** Use mirror plots, precursor
70 agreement, ion/adduct compatibility, and orthogonal evidence.
71
72## Current API Guardrails
73
74These points prevent the most common failures from pre-0.33 examples:
75
76- Use `ModifiedCosineGreedy` or `ModifiedCosineHungarian`; `ModifiedCosine` was
77 removed in 0.32.0.
78- Do not call `add_losses()`. It was removed in 0.27.0; use
79 `spectrum.losses`, `spectrum.compute_losses(...)`, or
80 `NeutralLossesCosine` directly.
81- `SpectrumProcessor` is not callable. Use `process_spectrum()` or
82 `process_spectra()`.
83- `process_spectra()` returns `(processed_spectra, processing_report)`.
84- `Scores.scores` is a `StackedSparseArray`, often with separate structured
85 fields such as `CosineGreedy_score` and `CosineGreedy_matches`.
86- `scores_by_query()` returns `(reference_spectrum, score_record)` pairs, not
87 reference indices.
88- Prefer `spectra` in parameter names. The legacy spelling `spectrums` is
89 deprecated.
90- Never load pickle files from an untrusted source; unpickling can execute code.
91
92See `references/migration.md` for a complete old-to-current mapping.
93
94## Quick Start: Clean and Search a Library
95
96```python
97from matchms import SpectrumProcessor, calculate_scores
98from matchms.filtering import (
99 default_filters,
100 normalize_intensities,
101 require_minimum_number_of_peaks,
102 select_by_relative_intensity,
103)
104from matchms.importing import load_spectra
105from matchms.similarity import ModifiedCosineGreedy
106
107
108def load_and_process(path):
109 spectra = [default_filters(spectrum) for spectrum in load_spectra(path)]
110 processor = SpectrumProcessor(
111 [
112 normalize_intensities,
113 (select_by_relative_intensity, {"intensity_from": 0.01}),
114 (require_minimum_number_of_peaks, {"n_required": 5}),
115 ]
116 )
117 processed, _ = processor.process_spectra(
118 spectra,
119 progress_bar=False,
120 create_report=False,
121 )
122 return processed
123
124
125references = load_and_process("library.msp")
126queries = load_and_process("queries.mgf")
127
128metric = ModifiedCosineGreedy(tolerance=0.02)
129scores = calculate_scores(
130 references=references,
131 queries=queries,
132 similarity_function=metric,
133)
134
135score_name = "ModifiedCosineGreedy_score"
136matches_name = "ModifiedCosineGreedy_matches"
137for query in queries:
138 ranked = scores.scores_by_query(query, name=score_name, sort=True)
139 for reference, values in ranked[:5]:
140 print(
141 query.get("spectrum_id", query.get("id")),
142 reference.get("compound_name", reference.get("spectrum_id")),
143 float(values[score_name]),
144 int(values[matches_name]),
145 )
146```
147
148`SpectrumProcessor` automatically orders built-in filters according to matchms's
149filter order. The aggregate `default_filters` callable is not in that registry,
150so run it first as above or expand its nine component filters. Inspect
151`processor.processing_steps` and preserve it with results.
152
153## Pair Scoring
154
155Similarity classes expose `pair()` for one reference/query pair. Cosine-family
156results are structured NumPy scalars:
157
158```python
159from matchms.similarity import CosineGreedy
160
161result = CosineGreedy(tolerance=0.02).pair(reference, query)
162similarity = float(result["score"])
163matched_peaks = int(result["matches"])
164```
165
166Use `calculate_scores()` for matrix-oriented methods such as
167`FlashSimilarity`; its single-pair path is supported but intentionally not the
168optimized path.
169
170## Choose a Similarity Method
171
172- `CosineGreedy` — standard peak cosine with greedy peak assignment.
173- `CosineHungarian` — exact assignment; slower, useful for benchmarks.
174- `CosineLinear` — current linear-scaling cosine implementation.
175- `ModifiedCosineGreedy` — permits precursor-delta-shifted matches; common for
176 analog search.
177- `ModifiedCosineHungarian` — exact modified-cosine assignment.
178- `NeutralLossesCosine` — compares losses computed from precursor and fragments.
179- `BlinkCosine` — fast BLINK-style cosine approximation for larger matrices.
180- `FlashSimilarity` — optimized matrix scoring using spectral entropy or cosine
181 with fragment, neutral-loss, or hybrid matching.
182- `BinnedEmbeddingSimilarity` — binned spectral vectors and optional approximate
183 nearest-neighbor indexing.
184- `PrecursorMzMatch`, `ParentMassMatch`, `MetadataMatch` — candidate masks or
185 metadata constraints, not rich spectral scores.
186- `FingerprintSimilarity` — molecular-structure similarity; it is not spectral
187 similarity and requires fingerprints prepared from valid structures.
188
189Read `references/similarity.md` before choosing a fast method, combining scores,
190or interpreting structured outputs.
191
192## Large Comparisons
193
194For all-vs-all scoring of one collection, set `is_symmetric=True`:
195
196```python
197scores = calculate_scores(
198 references=spectra,
199 queries=spectra,
200 similarity_function=CosineGreedy(tolerance=0.02),
201 array_type="sparse",
202 is_symmetric=True,
203)
204```
205
206For a precursor-gated search, compute and filter `PrecursorMzMatch` first, then
207calculate the spectral metric only on retained coordinates through `Pipeline`
208or `Scores.calculate(...)`. See `references/workflows.md`.
209
210Do not choose a universal "identification threshold." Score distributions
211depend on preprocessing, mass accuracy, collision conditions, library quality,
212and metric. At minimum, retain both score and matched-peak count for
213cosine-family methods.
214
215## Bundled Library-Search CLI
216
217`scripts/library_search.py` provides a reproducible query-versus-library search
218with current score extraction, pair-count limits, preprocessing, and CSV output:
219
220```bash
221uv run python scripts/library_search.py \
222 queries.mgf library.msp hits.csv \
223 --metric modified \
224 --tolerance 0.02 \
225 --top-k 10 \
226 --min-score 0.6 \
227 --min-matches 5
228```
229
230Run `--help` for fast metrics, preprocessing options, identifier fields,
231overwrite control, and the explicit large-matrix override.
232
233## Spectrum Objects and Visualization
234
235```python
236import numpy as np
237from matchms import Spectrum
238
239spectrum = Spectrum(
240 mz=np.array([100.0, 150.0, 200.0]),
241 intensities=np.array([0.2, 1.0, 0.4]),
242 metadata={"spectrum_id": "query-1", "precursor_mz": 250.5},
243)
244
245print(spectrum.peaks.mz)
246print(spectrum.get("precursor_mz"))
247losses = spectrum.compute_losses(loss_mz_from=5.0, loss_mz_to=200.0)
248spectrum.plot()
249spectrum.plot_against(reference_spectrum)
250```
251
252## References
253
254Read only the reference needed for the task:
255
256- `references/importing_exporting.md` — formats, return types, generic I/O,
257 mzSpecLib, score serialization, and pickle safety
258- `references/filtering.md` — current filter catalog, clone/`None` semantics,
259 default filters, ordering, and `SpectrumProcessor`
260- `references/similarity.md` — all current similarity classes, outputs,
261 candidate masking, performance, and interpretation
262- `references/workflows.md` — library search, sparse gating, `Pipeline`, networks,
263 plotting, and provenance
264- `references/migration.md` — breaking changes and deprecated APIs
265- `references/sources.md` — authoritative docs, release notes, user guides, and
266 scientific publications used for this refresh
267
268## Non-Negotiable Checks
269
270- Never compare raw queries against differently processed references.
271- Never use modified or neutral-loss scoring without valid precursor metadata.
272- Never assume a `Scores` value is a plain float; inspect `score_names`.
273- Never treat a high similarity score alone as confirmed identification.
274- Never deserialize untrusted pickle data.
275- Never launch an unbounded all-pairs comparison without estimating pair count.
276