single-cell-proteomics-data-processing
Skill1.1k starsChanged 8 months agoMITView on GitHub
Load, inspect, centroid, and extract features from raw LC-MS/MS data files. This is Step 1 of the proteomics pipeline — all downstream peptide identification and quantification steps require centroided, quality-checked spectra as input. If you ask a general AI to "process my mzML files for proteomics," it will: This skill encodes the correct methodological decisions: pyOpenMS is the Python interface to OpenMS (Röst et al., 2016), a C++ framework for computational mass spectrometry. It provides direct access to the full…
Trending
Quiet this year.thin dataabout the whole repository
Who's talking about PharMolix/OpenBioMed
The biggest 1 of 1 mention linking to the repository that our crawl found. Each line is their own headline.
In this repository45 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- admet-predictionSkill
- antibody-design-iggmSkill
- antibody-structure-prediction-tfoldSkill
- binding-affinity-prediction-prodigySkill
- biomedical-literature-searchSkill
- biomed-skill-creatorSkill
- biomed-skill-routerSkill
- cellxgene-census-querySkill
- chembl-querySkill
- disease-drug-intelligenceSkill
- drug-candidate-discoverySkill
- drug-drug-interaction-analysisSkill
- drug-lead-analysisSkill
- functional-protein-designSkill
- iupac-name-identification-biot5Skill
- kegg-querySkill
- molecule-biochemical-significance-query-biot5Skill
- mutation-design-aavSkill
- mutation-design-gfpSkill
- ppi-string-querySkill
- protein-function-predictionSkill
- protein-ligand-binding-analysis-plipSkill
- protein-mutation-analysisSkill
- protein-structure-design-boltzgenSkill
- protein-subcellular-localization-prediction-biot5Skill
- pubchem-querySkill
- retrosynthesis-planningSkill
- similar-protein-retrievalSkill
- single-cell-atac-seq-peak-calling-annotaionSkill
- single-cell-atac-seq-qc-processingSkill
- single-cell-foundation-model-geneformerSkill
- single-cell-foundation-model-langcellSkill
- single-cell-foundation-model-scgptSkill
- single-cell-multi-omics-analysis-scviSkill
- single-cell-multi-omics-data-harmonizationSkill
- single-cell-proteomics-peptide-identificationSkill
- single-cell-scrna-seq-analysis-scanpySkill
- single-cell-foundation-model-stofmSkill
- spatial-transcriptomics-spatial-data-ioSkill
- structure-prediction-boltz-2Skill
- target-based-lead-designSkill
- target-drug-reportSkill
- text-based-molecule-editingSkill
- uniprot-querySkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 6 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 25
If you ask a general AI to "process my mzML files for proteomics," it will:
- Distinctive: line 27
Not distinguish between profile-mode and centroid-mode spectra (critical difference for downstream tools)
- Distinctive: line 28
Use incorrect pyOpenMS API calls (the API changed significantly between versions 2.x and 3.x)
- Distinctive: line 30
Not explain the difference between peak picking and feature detection, or when each is needed
- Distinctive: line 272
EIC tolerance: Use ± 5–10 ppm for Orbitrap data (e.g., ± 0.003 Da at m/z 600).
- Distinctive: line 278
If you use this skill in a publication, please cite:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Raw Mass Spectrometry Data Processing (pyOpenMS)
Load, inspect, centroid, and extract features from raw LC-MS/MS data files. This is Step 1 of the proteomics pipeline — all downstream peptide identification and quantification steps require centroided, quality-checked spectra as input.
What it does
- Loads raw or profile-mode spectra from mzML, mzXML, or vendor-converted files using pyOpenMS
- Inspects run-level QC metrics: total ion current (TIC), scan counts per MS level, m/z and RT ranges
- Converts profile-mode spectra to centroid mode using PeakPickerHiRes
- Extracts MS1 and MS2 spectra separately for downstream use
- Detects LC-MS features (isotope envelopes) using FeatureFinder for label-free quantification
- Extracts extracted ion chromatograms (EIC) for targeted m/z values
- Converts between mzML, mzXML, and featureXML formats
- Generates per-run QC plots (TIC, scan distribution, peak width)
Why this exists
If you ask a general AI to "process my mzML files for proteomics," it will:
- Not distinguish between profile-mode and centroid-mode spectra (critical difference for downstream tools)
- Use incorrect pyOpenMS API calls (the API changed significantly between versions 2.x and 3.x)
- Skip quality control checks that reveal injection failures, column issues, or contamination
- Not explain the difference between peak picking and feature detection, or when each is needed
- Produce centroided output without verifying peak width or mass accuracy
This skill encodes the correct methodological decisions:
- Checks MS level distribution before processing to confirm DDA vs. DIA acquisition mode
- Applies PeakPickerHiRes (correct algorithm) not PeakPickerIterative (for Orbitrap data)
- Separates MS1 feature detection (for LFQ) from MS2 centroiding (for database search)
- Generates TIC plots to visually confirm run quality before investing compute time in search
- Uses pyOpenMS 3.x API (
MSExperiment,MzMLFile) which differs from 2.x
Reference Methods
pyOpenMS is the Python interface to OpenMS (Röst et al., 2016), a C++ framework for computational mass spectrometry. It provides direct access to the full OpenMS algorithm library including peak picking, feature detection, alignment, and quantification.
PeakPickerHiRes: Gaussian-based centroiding algorithm optimized for high-resolution instruments (Orbitrap, Q-TOF). Fits a Gaussian to each isotope peak and reports the apex m/z and intensity. Requires profile-mode input.
FeatureFinderCentroided: Identifies LC-MS features by grouping isotope envelopes across consecutive MS1 scans. Outputs feature maps with m/z, RT, intensity, and charge state per feature. Used as input to label-free quantification.
File formats:
mzML: Open, XML-based vendor-neutral format. Use for all pipeline steps.mzXML: Older open format; convert to mzML with msconvert if needed.featureXML: OpenMS-native format for feature maps.pepXML/mzIdentML: Downstream peptide identification results formats.
Usage (Python — pyOpenMS)
import pyopenms as oms
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# ── Step 1: Load mzML file ────────────────────────────────────────────────────
exp = oms.MSExperiment()
oms.MzMLFile().load("sample.mzML", exp)
print(f"Spectra loaded: {exp.getNrSpectra()}")
print(f"Chromatograms: {exp.getNrChromatograms()}")
# ── Step 2: QC — inspect scan distribution ────────────────────────────────────
ms1_scans, ms2_scans = [], []
for spec in exp:
level = spec.getMSLevel()
if level == 1:
ms1_scans.append(spec.getRT())
elif level == 2:
ms2_scans.append(spec.getRT())
print(f"MS1 scans: {len(ms1_scans)}")
print(f"MS2 scans: {len(ms2_scans)}")
print(f"MS2/MS1 ratio: {len(ms2_scans)/len(ms1_scans):.1f} "
f"(expect 5–20 for typical DDA)")
# ── Step 3: Plot Total Ion Chromatogram (TIC) ─────────────────────────────────
tic_rt, tic_int = [], []
for spec in exp:
if spec.getMSLevel() == 1:
tic_rt.append(spec.getRT() / 60) # convert to minutes
tic_int.append(spec.calculateTIC())
fig, ax = plt.subplots(figsize=(10, 3))
ax.plot(tic_rt, tic_int, lw=0.8, color="#2166AC")
ax.set_xlabel("Retention time (min)")
ax.set_ylabel("Total ion current")
ax.set_title("TIC — sample.mzML")
plt.tight_layout()
plt.savefig("figures/tic_sample.pdf")
plt.close()
# ── Step 4: Check acquisition mode (profile vs centroid) ─────────────────────
first_ms1 = next(s for s in exp if s.getMSLevel() == 1)
is_centroid = first_ms1.getType() == oms.SpectrumSettings.CENTROID
print(f"Acquisition mode: {'centroid' if is_centroid else 'profile'}")
# ── Step 5: Centroiding (only if profile-mode) ────────────────────────────────
if not is_centroid:
picker = oms.PeakPickerHiRes()
params = picker.getParameters()
params.setValue("signal_to_noise", 1.0) # lower = more peaks; 0.0 = all peaks
params.setValue("ms_levels", [1, 2])
picker.setParameters(params)
centroided_exp = oms.MSExperiment()
picker.pickExperiment(exp, centroided_exp, check_spectrum_type=False)
print(f"Centroided spectra: {centroided_exp.getNrSpectra()}")
oms.MzMLFile().store("sample_centroided.mzML", centroided_exp)
else:
centroided_exp = exp
print("Already centroided — no peak picking needed")
# ── Step 6: Extract a single MS2 spectrum ────────────────────────────────────
ms2_spectra = [s for s in centroided_exp if s.getMSLevel() == 2]
spec = ms2_spectra[0]
mz_array, int_array = spec.get_peaks()
precursor = spec.getPrecursors()[0]
print(f"\nExample MS2 spectrum:")
print(f" Precursor m/z: {precursor.getMZ():.4f}")
print(f" Precursor charge: {precursor.getCharge()}")
print(f" Fragment peaks: {len(mz_array)}")
print(f" RT: {spec.getRT()/60:.2f} min")
# ── Step 7: Feature detection (MS1, for LFQ) ──────────────────────────────────
ff = oms.FeatureFinder()
ff_name = "centroided"
features = oms.FeatureMap()
seeds = oms.FeatureMap()
ff_params = oms.FeatureFinder().getParameters(ff_name)
# Extract MS1-only experiment for feature finding
ms1_exp = oms.MSExperiment()
for spec in centroided_exp:
if spec.getMSLevel() == 1:
ms1_exp.addSpectrum(spec)
ff.run(ff_name, ms1_exp, features, ff_params, seeds)
features.setUniqueIds()
print(f"\nFeatures detected: {features.size()}")
oms.FeatureXMLFile().store("sample_features.featureXML", features)
# ── Step 8: Export features as DataFrame ─────────────────────────────────────
rows = []
for feat in features:
rows.append({
"feature_id": feat.getUniqueId(),
"mz": feat.getMZ(),
"rt_min": feat.getRT() / 60,
"intensity": feat.getIntensity(),
"charge": feat.getCharge(),
"rt_start": feat.getConvexHull().getBoundingBox().minX() / 60,
"rt_end": feat.getConvexHull().getBoundingBox().maxX() / 60,
})
features_df = pd.DataFrame(rows)
features_df.to_csv("sample_features.csv", index=False)
print(features_df.head())
# ── Step 9: Extracted ion chromatogram (EIC) for a target m/z ────────────────
target_mz = 524.2736 # example: target peptide precursor m/z
tolerance = 0.02 # ± 20 mDa (Orbitrap); use 0.05 for Q-TOF
eic_rt, eic_int = [], []
for spec in centroided_exp:
if spec.getMSLevel() == 1:
mzs, ints = spec.get_peaks()
mask = np.abs(mzs - target_mz) <= tolerance
eic_rt.append(spec.getRT() / 60)
eic_int.append(float(ints[mask].sum()) if mask.any() else 0.0)
fig, ax = plt.subplots(figsize=(8, 3))
ax.plot(eic_rt, eic_int, lw=1.2, color="#E64B35")
ax.set_xlabel("Retention time (min)")
ax.set_ylabel("Intensity")
ax.set_title(f"EIC — m/z {target_mz:.4f} ± {tolerance*1000:.0f} mDa")
plt.tight_layout()
plt.savefig(f"figures/eic_{target_mz:.2f}.pdf")
plt.close()Batch processing multiple runs
from pathlib import Path
mzml_files = list(Path("raw/").glob("*.mzML"))
for mzml_path in mzml_files:
exp = oms.MSExperiment()
oms.MzMLFile().load(str(mzml_path), exp)
# QC summary
ms1 = sum(1 for s in exp if s.getMSLevel() == 1)
ms2 = sum(1 for s in exp if s.getMSLevel() == 2)
print(f"{mzml_path.name}: {ms1} MS1, {ms2} MS2")
# Centroid if needed
first_ms1 = next(s for s in exp if s.getMSLevel() == 1)
if first_ms1.getType() != oms.SpectrumSettings.CENTROID:
picker = oms.PeakPickerHiRes()
out_exp = oms.MSExperiment()
picker.pickExperiment(exp, out_exp, check_spectrum_type=False)
out_path = Path("centroided") / mzml_path.name
oms.MzMLFile().store(str(out_path), out_exp)
print(f" → centroided: {out_path}")Example Output
Raw MS Data Processing
=======================
File: HeLa_digest_rep1.mzML
Spectra loaded: 18,432
Chromatograms: 0
Scan distribution:
MS1 scans: 1,842
MS2 scans: 16,590
MS2/MS1 ratio: 9.0 (expect 5–20 for typical DDA)
Acquisition mode: profile
Centroiding with PeakPickerHiRes...
Centroided spectra: 18,432 ✓
Feature detection (MS1):
Features detected: 14,271
Charge states: z=1 (12%), z=2 (38%), z=3 (31%), z=4+ (19%)
RT range: 5.2 – 118.4 min
m/z range: 300.1 – 1,650.4
Example MS2 spectrum (RT = 42.3 min):
Precursor m/z: 524.2736
Precursor charge: 2+
Fragment peaks: 187
Exported:
HeLa_digest_rep1_centroided.mzML
HeLa_digest_rep1_features.featureXML
HeLa_digest_rep1_features.csv (14,271 features)
figures/tic_HeLa_digest_rep1.pdfInterpretation Guide
- MS2/MS1 ratio: A ratio of 5–20 is typical for DDA experiments. Ratio < 3 suggests the instrument was triggering few MS2 events (check intensity threshold settings); ratio > 30 is unusual
- Profile vs centroid: Profile data shows Gaussian peak shapes per m/z; centroid data shows single m/z values per peak. Database search tools (MSFragger, Comet) require centroid input
- TIC shape: A broad, smooth Gaussian-like TIC indicates a good LC gradient. Flat TIC at the start/end is normal (column equilibration). Sudden drops mid-gradient indicate injection failure or column clogging
- Feature count: 10,000–30,000 features per run is typical for a HeLa cell digest on Orbitrap. Fewer than 5,000 suggests poor digest efficiency, short gradient, or injection problems
- Charge state distribution: z=2 and z=3 should dominate (> 60% combined) for a typical tryptic digest. High z=1 fraction suggests incomplete digestion or non-tryptic peptides
- EIC tolerance: Use ± 5–10 ppm for Orbitrap data (e.g., ± 0.003 Da at m/z 600); use ± 50 ppm or ± 0.05 Da for Q-TOF data
Citation
If you use this skill in a publication, please cite:
- Röst, H.L. et al. (2016). OpenMS: a flexible open-source software platform for mass spectrometry data analysis. Nature Methods, 13(9), 741–748.
- Sturm, M. et al. (2008). OpenMS — an open-source software framework for mass spectrometry. BMC Bioinformatics, 9, 163.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

