Convert Thermo Orbitrap .raw files to polarity-split .mzML files using a single Docker command — no local dependencies required.
# Build the image (one-time)
docker build -t raw2mzml .
# Run — replace the left side of the colon with your data folder
docker run --rm -v /path/to/your/raw/files:/data/raw raw2mzmlOutput appears in your folder under mzML/ and mzML/split/.
New to Docker? See HOW_TO_USE.md for a step-by-step guide (Mac, Windows, Linux) with troubleshooting.
Thermo .raw files
│
▼ Step 1 — ThermoRawFileParser v2.0.0 (.NET 8, no Mono)
.mzML (indexed mzML, centroided, both polarities combined)
│
▼ Step 2 — split_polarity.py (Python + lxml)
_pos.mzML + _neg.mzML (one file per polarity per sample)
- Step 1 applies vendor (Thermo) centroiding — profile data is not preserved. Outputs indexed mzML with instrument metadata JSON (
-m 1) - Step 2 splits on PSI-MS CV terms
MS:1000130(positive) andMS:1000129(negative); output files are plain (non-indexed) mzML - Works with any Thermo Orbitrap acquisition type (LC-MS, DI-MS, GC-MS)
DDA / MS2 note: In data-dependent acquisition mode, MS2 spectra typically do not carry an explicit polarity CV term — polarity is inherited from the triggering MS1 scan.
split_polarity.pyonly splits spectra with explicit polarity tags; MS2 spectra without them are silently dropped. For DI-MS and full-scan LC-MS (MS1 only) this has no effect. For DDA workflows with MS2 data, use a dedicated converter (e.g. MSConvert with scan filter).
your-data-folder/
├── sample_1.raw ← original files, untouched
├── sample_2.raw
└── mzML/
├── sample_1.mzML ← converted, both polarities
├── sample_1-metadata.json ← instrument + run metadata
├── sample_2.mzML
├── sample_2-metadata.json
└── split/
├── sample_1_pos.mzML ← positive mode only
├── sample_1_neg.mzML ← negative mode only
├── sample_2_pos.mzML
└── sample_2_neg.mzML
| File | Purpose |
|---|---|
Dockerfile |
Debian slim (linux/amd64) + .NET 8 + Python 3 + lxml + ThermoRawFileParser v2.0.0 |
run_pipeline.sh |
Container entrypoint — validates input, runs both steps, fixes file ownership |
split_polarity.py |
Splits interleaved mzML by polarity CV term |
docker-compose.yml |
Convenience wrapper — edit volume path, then docker compose up |
| Environment variable | Default | Description |
|---|---|---|
RAW_DIR |
/data/raw |
Input directory inside the container |
MZML_DIR |
/data/raw/mzML |
Output directory inside the container |
HOST_UID |
UID of mounted folder | Output file ownership on the host |
HOST_GID |
GID of mounted folder | Output file group on the host |
Override with -e:
docker run --rm \
-v /your/data:/data/raw \
-e HOST_UID=$(id -u) \
-e HOST_GID=$(id -g) \
raw2mzmlRequirements: Python 3 with lxml, ThermoRawFileParser (v1.4.5 via Mono on macOS/Linux, or native on Windows)
# Step 1 — convert (macOS/Linux with Mono installed locally)
mono /path/to/ThermoRawFileParser.exe \
-d /path/to/raw \
-o /path/to/raw/mzML \
-f 2 -m 1 -l 2
# Step 2 — split
MZML_DIR=/path/to/raw/mzML python3 split_polarity.pyMIT — see LICENSE.