Running noninteractively
For scripting, batch processing, and reproducible runs, drive QSMxT from the command line. (Prefer to point and click? See Running interactively — everything below is available there too.)
Running the pipeline
Section titled “Running the pipeline”qsmxt run is the heart of the tool: it discovers every phase/magnitude run in a
BIDS dataset and reconstructs a quantitative susceptibility map for each.
qsmxt run <BIDS_DIR> [OUTPUT_DIR]<BIDS_DIR>— input BIDS directory[OUTPUT_DIR]— defaults to<BIDS_DIR>; results go to<OUTPUT_DIR>/derivatives/qsmxt/
With no options, QSMxT runs with sensible defaults end to end. Need a BIDS dataset first? See Converting DICOMs to BIDS below.
The stages
Section titled “The stages”Each run flows through the pipeline below. The method at every stage is configurable — see Algorithms.
- Masking — generate a brain/region mask (
--mask-preset, or custom--masksections). - Phase offset removal — remove receiver phase offsets on multi-echo data.
- Phase unwrapping —
romeoorlaplacian. - Echo combination / B0 mapping — combine echoes into a field map
(
--b0-estimation,--b0-weight-type). - Background field removal —
vsharp,pdf,lbv, and more. - Dipole inversion —
ilsqr(default),rts,tv,tgv,medi, … (31 algorithms). - Referencing — reference the susceptibility values (e.g. to the mean).
Not every inversion runs every stage: total-field methods (TFI, QSMART, AutoQSM,
NeXtQSM, MEDI with --medi-smv, multi-echo TGV) skip background field removal,
and the wrapped-phase methods (iQSM, iQSM+, single-echo TGV) skip unwrapping and
echo combination too. See Algorithms.
Choosing algorithms
Section titled “Choosing algorithms”qsmxt run study/bids \ --mask-preset robust-threshold \ --unwrapping-algorithm romeo \ --bf-algorithm vsharp \ --qsm-algorithm ilsqr| Option | Choices |
|---|---|
--qsm-algorithm |
20 classical (rts, tv, tkd, tgv, medi, ilsqr, …) and 11 deep-learning (xqsm, qsmnet, iqsm, …) |
--unwrapping-algorithm |
romeo, laplacian |
--bf-algorithm |
vsharp, pdf, lbv, ismv, sharp, resharp, harperella, iharperella, bfrnet, iqfm |
--mask-preset |
robust-threshold, bet, hd-bet, bet-and-phase, rs2-net, mindgrab |
--masking-input |
magnitude-first, magnitude, magnitude-last, phase-quality |
Every value of every option is listed in the CLI reference and described in Algorithms.
--masking-input overrides the image the mask is computed from and combines
with --mask-preset — e.g. --mask-preset bet --masking-input magnitude-first
runs BET on the first-echo magnitude. For fully custom masking, see --mask
in Algorithms.
Selecting runs
Section titled “Selecting runs”Process only part of a dataset with glob patterns:
# Only these subjectsqsmxt run study/bids --include "sub-01*" "sub-02*"
# Everything except a sessionqsmxt run study/bids --exclude "*ses-pilot*"
# Cap the number of echoes usedqsmxt run study/bids --num-echoes 4Multi-echo phase handling
Section titled “Multi-echo phase handling”# Receiver phase-offset removal (on by default for multi-echo)qsmxt run study/bids --phase-offset-removal true
# Bipolar readout correction (needs ≥ 3 echoes)qsmxt run study/bids --bipolar-correctionROMEO unwrapping has several modes — per-echo (default) or template-based,
with inter-echo 2π correction. See qsmxt run --help for the full set of
--romeo-* flags.
Using a configuration file
Section titled “Using a configuration file”Reproduce a run exactly by saving settings to a TOML file and passing --config:
qsmxt init > pipeline.toml # generate a starting configqsmxt run study/bids --config pipeline.tomlSee Configuration.
Re-running
Section titled “Re-running”Intermediate results are cached to disk. Re-running the same dataset skips any stage that already completed, so tweaking a late-stage option doesn’t recompute the whole pipeline.
Output
Section titled “Output”study/bids/derivatives/qsmxt/└── sub-01/ ├── anat/ │ ├── sub-01_…_Chimap.nii │ ├── sub-01_…_Chimap.json │ ├── sub-01_…_mask.nii │ ├── sub-01_…_desc-qsm_mask.nii │ └── sub-01_…_part-mag_T2starw.nii └── fmap/ ├── sub-01_…_desc-total_fieldmap.nii └── sub-01_…_desc-total_magnitude.niiOutputs are uncompressed NIfTI (.nii), each with a JSON sidecar recording how it
was made (GeneratedBy, units, and for susceptibility maps the reference). The
total field is published in Hz under fmap/. Every file and its name is listed
in Output files.
mask is the brain mask; desc-qsm_mask is the part of it the susceptibility map
is defined on — the brain mask less the rim that background-field removal eroded.
The Chimap is referenced over, and is 0 outside, desc-qsm_mask; the χ-separation
maps (--do-chisep) are fitted over it and are 0 outside it too.
At the top of derivatives/qsmxt/, methods.md describes the processing in
prose ready for a methods section, with citations for the exact methods used for
your data and parameters; pipeline.svg draws the same pipeline, one box per
step (pipeline.mmd is the same graph in Mermaid);
pipeline_config.toml holds the resolved settings (reusable with --config),
and qsmxt.log the log.
Some things are only decided as a run goes: a mask supplied with
--use-custom-masks that cannot be used is computed instead, R2′ is measured
where a multi-echo spin-echo scan allows and estimated otherwise. Once every run
is done, methods.md and the graph are written from what the runs did: a choice
every run made is stated as done, and the graph’s boxes say how many runs
skipped a step or decided something in it. They cover every run in the output
directory that completed with the current settings, whichever command
processed it, so re-running one subject with --include does not narrow them;
a run last processed with other settings, or whose last attempt did not finish,
is left out. A run processed differently from the
rest gets its own methods text and graph in changes/ (<run>_methods.md,
<run>_desc-ran_pipeline.mmd and .svg); the folder is only there when some
run differs. Each run’s methods text, a record of what each step did and why
(*_runrecord.json), and its graph are also kept in its workflow/ directory.
qsmxt run --dry prints the pipeline graph and the methods text as planned,
without running anything or writing any file.
The reference summary
Section titled “The reference summary”Every susceptibility map is referenced (see
Referencing), and each map’s sidecar
records what with QsmReference (mean, none, or the region), QsmReferenceOffsetPpm
(the value subtracted), QsmReferenceVoxels (how many voxels it was measured over)
and, for a region, QsmReferenceLabels (its label ids). The same facts for every
map of every run are collected in desc-reference_summary.tsv at the top of the
derivatives:
| Column | Meaning |
|---|---|
subject, session, acquisition, reconstruction, inversion, run |
The run’s BIDS entities |
map |
The map, by its BIDS suffix with any desc- (Chimap, desc-singlepass_Chimap, desc-cosmos_Chimap, …) |
reference |
What zero was pinned to (QsmReference) |
offset_ppm |
The value subtracted, in ppm (QsmReferenceOffsetPpm) |
n_voxels |
Voxels the reference was measured over (QsmReferenceVoxels) |
It is the file to scan for a subject whose reference region came out small or empty.
Exporting results as DICOM
Section titled “Exporting results as DICOM”Some workflows want the maps back in DICOM — to push them into a PACS, open them
in a clinical viewer, or hand them to a radiologist beside the source study.
--export-dicom writes a DICOM series for every final map alongside the NIfTIs:
qsmxt run study/bids --export-dicomEach map gets its own folder under the subject’s extra_files/, one file per
slice:
study/bids/derivatives/qsmxt/└── sub-01/ ├── anat/ │ └── sub-01_…_Chimap.nii └── extra_files/ └── sub-01_Chimap_dicoms/ ├── sub-01_Chimap_0001.dcm ├── sub-01_Chimap_0002.dcm └── …Every final map the run produced is exported. χ needs no extra flag; the supplementary maps are exported once you’ve asked for them:
| Map | Produced by | Folder suffix / --dicom-outputs token |
|---|---|---|
| Susceptibility (χ) | the default pipeline | Chimap |
| SWI | --do-swi |
swi |
| SWI minIP | --do-swi |
minIP |
| T2* | --do-t2starmap |
T2starmap |
| R2* | --do-r2starmap |
R2starmap |
| R2 | --do-r2map |
R2map |
| R2′ | --do-r2primemap |
R2primemap |
| Paramagnetic χ | --do-chisep |
desc-paramagnetic_Chimap |
| Diamagnetic χ | --do-chisep |
desc-diamagnetic_Chimap |
| Total χ | --do-chisep |
desc-total_Chimap |
To export only some of them, pass those tokens to --dicom-outputs
(case-insensitive, comma- or space-separated):
qsmxt run study/bids --do-chisep --export-dicom \ --dicom-outputs chimap,desc-paramagnetic_chimap,desc-diamagnetic_chimapSMWI, the segmentation and the multi-orientation reconstructions stay NIfTI-only.
Filing them beside the source study. By default the derived series carry a synthesised identity: patient fields are
left empty and a stable StudyInstanceUID is derived from the subject and
session. That’s fine for a local viewer, but a PACS will file the maps as a study
of their own. Point --source-dicom at the original DICOMs and QSMxT inherits the
identity from the first readable DICOM it finds there — PatientID,
StudyInstanceUID, FrameOfReferenceUID, study date/time, accession number — so
the maps land beside the acquisition they came from:
qsmxt run study/bids --export-dicom --source-dicom /data/dicoms/sub-01SeriesInstanceUID and SOPInstanceUID are always newly generated: these are
distinct derived series, never a rewrite of the originals. Every instance is
tagged DERIVED\SECONDARY, and each map gets a stable SeriesNumber so viewers
list them in a predictable order.
A few more things worth knowing:
- Slice geometry (
ImageOrientationPatient,ImagePositionPatient,SliceLocation, spacing) is read from the output NIfTI’s affine, so the series overlays the source acquisition in a viewer and reflects any oblique resampling the run applied. - Instances are uncompressed MR Image Storage, Explicit VR Little Endian.
- Export is best-effort: a failure is logged and the run still succeeds.
--export-dicomis a pipeline setting, so it can live in a config file asexport_dicom = trueunder[pipeline], and it carries through toqsmxt slurm.--source-dicomand--dicom-outputsare flags onqsmxt runitself.
This is the mirror image of dicom-convert below,
which brings DICOMs in. Both directions are built into the binary — no external
converter to install.
Converting DICOMs to BIDS
Section titled “Converting DICOMs to BIDS”QSMxT needs BIDS-formatted input. The
dicom-convert command builds it for you from a directory of DICOMs, applying an
automatic best-guess classification to every series with no prompts — ideal for
scripting and batch jobs.
qsmxt dicom-convert <DICOM_DIR> <OUTPUT_DIR><DICOM_DIR>— input directory, searched recursively<OUTPUT_DIR>— output BIDS directory
Preview first with --dry-run
Section titled “Preview first with --dry-run”Before writing anything, inspect how QSMxT classifies your data:
qsmxt dicom-convert /data/dicoms study/bids --dry-runExample output:
Detected 4 unique series (auto-classified): acq-SWI3mm SWI_3mm [Magnitude] 2×TEs=[9.4…19.7]ms (uncombined, 32 coils) acq-SWI3mm SWI_3mm [Magnitude] 2×TEs=[9.4…19.7]ms acq-SWI3mm SWI_3mm [Magnitude] 2×TEs=[9.4…19.7]ms (filtered) acq-SWI3mm SWI_3mm [Phase] 2×TEs=[9.4…19.7]msEach row is a unique series, deduplicated across subjects, so you review a classification once even if many subjects share it.
What it handles
Section titled “What it handles”- Gradient-echo magnitude and phase — split correctly even when a vendor packs
both under a single
SeriesInstanceUID(e.g. some Philips/GE exports). - Multi-echo — echoes are detected and labelled
echo-N; the dry run reports the echo count and TE range. - T1-weighted structurals — MPRAGE / MP2RAGE / T1w series are recognised as
T1w, not magnitude. - Individual coil images — each coil element of an uncombined acquisition is
converted separately and labelled
rec-uncombined_coil-NN, instead of overwriting one another. - Derived reconstructions — a scanner-filtered magnitude (e.g. a SWI-filtered
series) is kept alongside the plain one with a
desc-filteredlabel rather than colliding with it.
Output is a BIDS tree of sub-*/anat/ NIfTIs with JSON sidecars (EchoTime in
seconds), ready for the pipeline. Already have NIfTIs? You can assemble a BIDS
dataset by hand — see Input data for the expected
layout, and run qsmxt validate
to check it’s pipeline-ready.
HPC & SLURM
Section titled “HPC & SLURM”For large cohorts, QSMxT can fan work out across an HPC cluster instead of running everything on one machine.
qsmxt slurm study/bids --account myaccount--account (the SLURM account to charge) is required. This writes SLURM batch
scripts for your dataset to <OUTPUT_DIR>/derivatives/qsmxt/slurm/, and with
--submit submits them. Run
qsmxt slurm --help for the available options (partition, time limits,
resource requests, and run selection).
qsmxt slurm accepts the same pipeline options as qsmxt run (algorithms,
masking, per-algorithm parameters, --config, --num-echoes, --force,
--clean-intermediates, --debug, and DICOM export’s --source-dicom and
--dicom-outputs, …), so any qsmxt run command becomes a SLURM one by
swapping the subcommand and adding the scheduler flags:
qsmxt slurm study/bids --qsm-algorithm tgv --unwrapping-algorithm laplacian \ --account myaccount --time 04:00:00The settings are checked, and every run is checked against them, before any
script is written, so a bad setting is reported once rather than by every job.
The resolved pipeline is written to
<OUTPUT_DIR>/derivatives/qsmxt/pipeline_config.toml and every generated job
runs against that file.
How the jobs divide the work
Section titled “How the jobs divide the work”- One job per run (
qsmxt_<run>.sh) runsqsmxt run --no-dataset-steps --include <run>: that run’s pipeline and nothing else. It logs tologs/<run>.logand writes nothing at dataset level. - One aggregation job (
qsmxt_aggregate.sh) runsqsmxt aggregateover all the runs once every run job has succeeded (--dependency=afterok:<all run job ids>). It does what a localqsmxt rundoes after its runs finish:- multi-orientation (COSMOS/STI) reconstruction across the runs of each group;
desc-reference_summary.tsv, the dataset-level statistics table and cohort figures;- BIDS-Prov records under
prov/; dataset_description.json,pipeline_config.toml,methods.md,pipeline.mmd/.svg,changes/;qsmxt.log, which collects every run’s log followed by its own;--clean-intermediates, if you asked for it.
The result is the same dataset a local qsmxt run produces, apart from
timestamps and the command recorded in the provenance (qsmxt slurm …).
--submit submits the run jobs and then the aggregation job with the
dependency. Without it, bash <OUTPUT_DIR>/derivatives/qsmxt/slurm/submit.sh
does the same.
Each job’s memory request is estimated from its run’s size and the pipeline.
The aggregation job is sized for the largest multi-orientation group. --mem
sets one figure for every job instead, with a warning for any run estimated to
need more.
If a run job fails, SLURM never starts the aggregation job: with afterok it
stays pending (or is cancelled, depending on the cluster’s settings). Fix the
cause, re-run that run’s script (sbatch slurm/qsmxt_<run>.sh; its finished
steps are cached), then submit slurm/qsmxt_aggregate.sh yourself. qsmxt aggregate refuses any run that has not completed under the same
configuration, and names it.
Parallelism on a single node
Section titled “Parallelism on a single node”Even without a scheduler, a single qsmxt run is parallel. QSMxT processes runs
concurrently and detects available memory to choose a safe degree of parallelism
automatically, so it fills your cores without exhausting RAM.
Caching plays nicely with retries
Section titled “Caching plays nicely with retries”Because intermediate results are cached to disk, a job that is requeued or resumed picks up where it left off rather than recomputing completed stages — handy when a cluster preempts or time-limits a job.
A typical cluster workflow
Section titled “A typical cluster workflow”- Convert and validate on a login node or small interactive job:
Terminal window qsmxt dicom-convert /data/dicoms study/bidsqsmxt validate study/bids - Dial in settings (locally or via the TUI) and save them:
Terminal window qsmxt init > pipeline.toml - Generate and submit the jobs (one per run, then the aggregation job):
Terminal window qsmxt slurm study/bids --config pipeline.toml --account myaccount --submit