Skill Tracer
Skills › Scientific Agent Skills › pyopenms › convert_format.py

convert_format.py

97 lines · skills/pyopenms/scripts/convert_format.py at 5f2bc03

1#!/usr/bin/env python3
2"""
3Convert Between MS File Formats
4
5Convert spectral data between mzML, mzXML, and MGF, with optional MS-level and
6RT/intensity filtering. Uses FileHandler for transparent format detection on load.
7
8Supported conversions (by output extension): .mzML, .mzXML, .mgf
9
10Usage:
11 python convert_format.py input.mzXML output.mzML
12 python convert_format.py input.mzML peaks.mgf --ms-level 2
13 python convert_format.py input.mzML out.mzML --rt-min 60 --rt-max 600 --min-intensity 500
14"""
16import argparse
17import os
18import sys
20try:
21 import pyopenms as ms
22except ImportError:
23 print("Error: pyopenms not installed. Install with: uv pip install pyopenms")
24 sys.exit(1)
27def load_experiment(path):
28 exp = ms.MSExperiment()
29 ms.FileHandler().loadExperiment(path, exp)
30 return exp
33def filter_experiment(exp, ms_level=None, rt_min=None, rt_max=None, min_intensity=None):
34 out = ms.MSExperiment(exp)
35 selected = []
36 for spec in exp:
37 if ms_level is not None and spec.getMSLevel() != ms_level:
38 continue
39 rt = spec.getRT()
40 if rt_min is not None and rt < rt_min:
41 continue
42 if rt_max is not None and rt > rt_max:
43 continue
44 if min_intensity is not None:
45 mz, inten = spec.get_peaks()
46 keep = inten >= min_intensity
47 spec.select(keep.nonzero()[0].tolist())
48 selected.append(spec)
49 out.setSpectra(selected)
50 # These are spectrum filters; chromatograms remain unchanged unless an MS
51 # level is selected, in which case they are omitted.
52 if ms_level is not None:
53 out.setChromatograms([])
54 return out
57def store_experiment(exp, path):
58 ext = path.lower()
59 if ext.endswith(".mzml"):
60 ms.MzMLFile().store(path, exp)
61 elif ext.endswith(".mzxml"):
62 ms.MzXMLFile().store(path, exp)
63 elif ext.endswith(".mgf"):
64 ms.MascotGenericFile().store(path, exp)
65 else:
66 raise ValueError(f"Unsupported output extension: {path} (use .mzML, .mzXML, or .mgf)")
69def main():
70 parser = argparse.ArgumentParser(description="Convert/filter MS files between formats.")
71 parser.add_argument("input", help="Input file (mzML/mzXML/...)")
72 parser.add_argument("output", help="Output file (.mzML, .mzXML, or .mgf)")
73 parser.add_argument("--ms-level", type=int, help="Keep only spectra at this MS level")
74 parser.add_argument("--rt-min", type=float, help="Minimum retention time (s)")
75 parser.add_argument("--rt-max", type=float, help="Maximum retention time (s)")
76 parser.add_argument("--min-intensity", type=float, help="Drop peaks below this intensity")
77 args = parser.parse_args()
79 if not os.path.exists(args.input):
80 print(f"Error: file not found: {args.input}")
81 sys.exit(1)
83 print(f"Loading {args.input}...")
84 exp = load_experiment(args.input)
85 print(f" {exp.getNrSpectra()} spectra, {exp.getNrChromatograms()} chromatograms")
87 if any(v is not None for v in (args.ms_level, args.rt_min, args.rt_max, args.min_intensity)):
88 exp = filter_experiment(exp, args.ms_level, args.rt_min, args.rt_max, args.min_intensity)
89 print(f" after filtering: {exp.getNrSpectra()} spectra")
91 print(f"Writing {args.output}...")
92 store_experiment(exp, args.output)
93 print("Done.")
96if __name__ == "__main__":
97 main()