This repository builds a reliable, reproducible LCModel quantification baseline across five
MRS datasets - the NN (mrsnet) pipeline is measured against it. It runs from this checkout while
avoiding duplicated data: scanner DICOM/IMA/DCM/CSV exports, .dat, LCModel basis, and the in-vivo datasets are
read from configured external/ paths.
Canonical host: qyber.black/mrs/code-mrs-megapress-lcmodel (GitLab). A GitHub copy, if present, is a mirror.
make quant reproduces all five datasets. Each writes scratch LCModel computation to
runs/quant_<dataset>_<sequence>/ (git-ignored) and publishes compact summaries to
results/quant_<dataset>_<sequence>/ (git-tracked); a combined baseline is stitched into docs/.
| Dataset | make target |
What / metric |
|---|---|---|
| Phantom benchmark | quant_benchmark_megapress |
in-vitro ground truth; max-norm MAE, best source x preprocess arm |
| Big GABA MEGA-PRESS | quant_biggaba_megapress |
in-vivo, 3 vendors; GABA+/Cr vs published; basis x MM approach comparison |
| Big GABA PRESS | quant_biggaba_press |
in-vivo short-TE PRESS; metab/tCr consistency |
| Fitting challenge | quant_fitchallenge_press |
synthetic ground truth (ISMRM 2016); max-norm MAE on metab/tCr |
| WAND MEGA-PRESS | quant_wand_megapress |
single-site (Cardiff), 4 voxels; GABA+/Cr reproducibility |
Results and findings:
docs/quantification-results.md- the consolidated quantification results (all datasets, canonical run)docs/results-guide.md- what every results file is (per dataset)docs/best-lcmodel-baseline.md- best (adopted) option per dataset + why; approach tradeoffsdocs/relative-concentration-baseline.md- the combined baseline (generated bymake quant)docs/discussion-benchmark.md- phantom benchmark results, findings, reproducedocs/discussion-biggaba.md- Big GABA MEGA-PRESS + PRESS (3 vendors, 3/3 PASS vs published)docs/discussion-fitchallenge.md- ISMRM 2016 fitting challenge (synthetic ground truth)docs/discussion-wand.md- WAND single-site multi-region reproducibility
Scope and method:
docs/biggaba-scope.md- Big GABA + WAND scope + processing detaildocs/mm3co-scope.md- the MM3co (explicit co-edited MM) approach + A/Bdocs/inputs.md- how to obtain every external dataset from official sources; the benchmarkinfo.jsonformatdocs/development-log.md- granular development log (findings / method / code paths)
Publication and citation:
If you use this baseline, please cite:
Langbein FC, Shermer S. MRS MEGAPRESS/PRESS LCModel quantification baseline
(version 1.0.0). https://qyber.black/mrs/code-mrs-megapress-lcmodel
Machine-readable metadata is in CITATION.cff. See also
CHANGELOG.md.
Contributing and support:
CONTRIBUTING.md- development workflow and merge requestsSUPPORT.md- how to ask questions and report issuesLICENSE- AGPL-3.0-or-later
The primary metric throughout is the max-normalised concentration MAE (per metabolite, with std /
95% CI), across the 5 core metabolites (Cr, GABA, Gln, Glu, NAA) plus gel mI/taurine where truth
exists; correlation and reconstruction fidelity are secondary. Dataset check/sync scripts live under
external/data-*/tools/.
The phantom benchmark separates three reconstruction-source concepts, compared as make quant arms:
archive replay: rerun the archived early-analysis preserved LCModel.RAWinputs with the preserved LCModel controls, then compare againstarchive/LCM_OFF_ALL.csvandarchive/LCM_DIFF_ALL.csv;dicom: generate LCModel.RAWinputs directly from scanner-processed benchmark DICOM/IMA/DCM/CSV spectra;scanner-dat: inventory Siemens scanner.datinputs under the benchmark tree and convert them to LCModel.RAWwith pure-Pythonmapvbvd.
The default standalone layout uses repo-local external/ paths:
external/
benchmark/ required phantom benchmark tree
basis-dist/lcmodel/megapress/ required LCModel MEGA-PRESS BASIS files
data-biggaba/ optional Big GABA (from NITRC)
data-fitchallenge/ optional ISMRM 2016 fitting challenge (from DRUM)
data-wand/ optional WAND ses-05 MRS subset (from GIN)
These directories may be symlinks. Obtain datasets from their official public
sources (DOIs, NITRC, Purdue, GIN, etc.) - see
docs/inputs.md for URLs, layouts, licenses, integrity
checks, and a wire-up checklist. Internal qyber.black mirrors are a lab
convenience only and are not required (and not a public data release).
Override paths with environment variables or by editing .env:
MRS_BENCHMARK_ROOT=external/benchmark
MRS_BASIS_ROOT=external/basis-dist/lcmodel/megapress
# Optional: override the tracked archive/raw/ directory with alternative LCModel RAWs.
# MRS_ARCHIVE_RAW_ROOT=/path/to/alternative/lcmodel-rawThe required external inputs are:
- benchmark source tree at
MRS_BENCHMARK_ROOT, containing per-seriesinfo.json(per-series metadata incl. per-sampleconcentrations), scanner-export sample folders, and scanner acquisitions under<SERIES>/RAW/(usually<SERIES>/RAW/<SAMPLE>/*.dat); - LCModel MEGA-PRESS BASIS files at
MRS_BASIS_ROOT, specificallyMEGAPRESS_edit_off_Siemens_3T.basisandMEGAPRESS_difference_Siemens_3T_kasier.basis.
Optional external inputs are:
MRS_ARCHIVE_RAW_ROOT, only when overriding the trackedarchive/raw/directory with alternative LCModel.RAWinput files. These files must match the preserved controls'FILRAWnames; they are not Siemens scanner.datfiles and not the benchmark<SERIES>/RAW/<SAMPLE>/folders;- in-vivo / challenge datasets under
external/data-*(Big GABA, ISMRM fitting challenge, WAND) for the correspondingmake quant_*targets.
The repository already contains the preserved LCModel aggregate CSVs
(archive/LCM_OFF_ALL.csv, archive/LCM_DIFF_ALL.csv) and preserved control files under
archive/control/, plus the original LCModel .RAW input files under archive/raw/. These three -
the preserved original LCModel run that make reproduce-archive replays - are grouped under archive/.
Create a local setup file from .env.example, then check configured paths:
make check-inputsSee docs/inputs.md for acquiring every dataset from official
sources, path conventions, and the full setup checklist.
See docs/comparison-tiers.md for valid comparison tiers and RAW fidelity gates.
From a source checkout:
python -m pip install -e .
mrs-megapress-lcmodel --helpFrom a release archive or wheel:
python -m pip install .
mrs-megapress-lcmodel check-inputsThe command works both as an installed console script (mrs-megapress-lcmodel)
and as a source-checkout module (python -m mrs_megapress_lcmodel). Runtime
outputs, external inputs, and the LCModel binary are resolved relative to the
current working project/data workspace, not the Python package install location.
Install public Git/LFS inputs where available:
mrs-megapress-lcmodel install-inputs --dataset benchmark --mode public
mrs-megapress-lcmodel install-inputs --dataset basis --mode publicInternal Cardiff/qyber users may also install internal mirrors:
mrs-megapress-lcmodel install-inputs --all-internal --mode internalBig GABA, WAND, and the ISMRM fitting challenge have public upstream
distribution routes and internal Git mirrors; check-inputs reports both when
those datasets are missing. Public release reproducibility must use the public
sources documented in docs/inputs.md, not the internal mirrors.
Run the full benchmark pipeline (LCModel execution under gitignored runs/, published CSVs under tracked results/, discussion doc under docs/):
make quant_benchmark_megapress # phantom benchmark -> results/quant_benchmark_megapress/
make publish-benchmark-results RUN_ID=quant_benchmark_megapress # re-publish from an existing runLatest published results: results/quant_benchmark_megapress/ and docs/results-quant_benchmark_megapress.md.
See docs/benchmark-matrix.md for the full input/preprocess matrix, CSV schemas, and workflow commands.
Build LCModel from the official Provencher source zip:
make setup-lcmodelLCModel is built automatically the first time a run command needs the default
binary .cache/lcmodel/bin/lcmodel. The setup command remains available for an
explicit preflight build. It downloads
http://s-provencher.com/pub/LCModel/source.zip, builds it with the included
Makefile when present or directly with gfortran for the current source zip
layout, and installs the resulting binary under .cache/lcmodel/bin/lcmodel.
If network access is unavailable, provide a local zip:
python3 -m mrs_megapress_lcmodel setup-lcmodel \
--source-zip /path/to/source.zip \
--install-dir .cache/lcmodelThe Makefile reads .env if present and uses venv/bin/python,
.venv/bin/python, or python3, in that order.
List available workflow targets:
make helpRun the current reproducible workflow with one output RUN_ID:
make run RUN_ID=<run-id>This builds LCModel if needed, checks inputs, replays the archived LCModel
RAW/control results, runs the full scanner .dat preprocessing profile matrix
with DICOM reference arms, publishes CSVs to results/<RUN_ID>/, and writes
pairwise spectrum plots under runs/<RUN_ID>/benchmark-dat-profiles/.
Archive replay is retained as the historical LCModel verification reference.
Check the configured external inputs:
make check-inputsWrite inventories without running LCModel:
make inventory
make inventory-scannerReplay archived controls and compare with the historical aggregate CSVs:
make reproduce-archiveFor backward-compatible comparison with the earlier run, the archived-control profile can still be run directly via the CLI.
The archived-control profile adds the explicit lines found in the archived
OFF/DIFF controls: PPMST=4.2, PPMEND=0.2, VITRO=T, SDDEGP=0, and
DEGPPM=0.
Inventory the scanner .dat inputs:
make prepare-scanner-datConvert scanner .dat files to LCModel inputs, run LCModel, and compare with
the benchmark ground truth:
make run-scanner-raw RUN_ID=<run-id> LCMODEL=/path/to/lcmodelThe default scanner export uses SCANNER_RAW_TRANSFORM=conjugate,
SCANNER_RAW_SCALE=3e8, SCANNER_RAW_SCALE_MODE=fixed,
SCANNER_EDIT_OFF_IDE=1, and SCANNER_EDIT_ON_IDE=0. The transform matches
the Siemens Twix convention read by mapvbvd to the preserved LCModel .RAW
convention; the fixed scale puts the exported FIDs into the same numerical range
as the preserved LCModel .RAW files so LCModel can fit them reliably. For
controlled normalisation experiments, set SCANNER_RAW_SCALE_MODE=sample-max;
this computes one maximum-magnitude scale over the reconstructed sample outputs
and applies the same effective scale to OFF and DIFF. Do not use per-spectrum
normalisation for LCModel inputs. The edit-state mapping is the benchmark mapping
validated by direct comparison with the preserved archive .RAW files.
Override these only for controlled source-comparison tests.
Select a scanner preprocessing profile with SCANNER_PREPROCESS:
make run-scanner-raw RUN_ID=<run-id> LCMODEL=/path/to/lcmodel SCANNER_PREPROCESS=phantom-megapressThe scanner converter uses Python mapvbvd to read Siemens Twix files. It uses
mapVBVD's readout-oversampling removal, groups MEGA-PRESS edit states by the
first suitable two-state Twix edit counter (Ide for svs_edit, Eco for the
eja_svs_mpress files observed here), derives receiver-coil weights from the
water-reference scan when available, and falls back to an SVD-derived coil
vector when a water reference is absent. It exports OFF from state 1 and
DIFF as state 0 - state 1, applies the configured RAW transform, and records
the transform, scale, edit-state mapping, and any non-finite Twix values
replaced before RAW export in each meta.json.
Diagnose scanner edit-state assignment without running LCModel:
python3 -m mrs_megapress_lcmodel diagnose-scanner-edit-states \
--generated-root runs/<run-id>/scanner-raw \
--output-dir runs/<run-id>/scanner-edit-state-diagnostics \
--raw-transform conjugate \
--raw-scale 3e8This compares candidate state0, state1, state1-state0, and
state0-state1 scanner spectra against preserved archive RAW targets.
All benchmark concentration errors are relative errors: each LCModel
concentration vector and each benchmark ground-truth vector is max-normalised per
spectrum before absolute errors are computed. The absolute LCModel-unit archive
delta table is kept only as a scale/provenance diagnostic; use
ground_truth_mae_summary.csv and archived_relative_delta_summary.csv for
relative concentration comparisons.
For benchmark-matrix runs, archive RAW is a third historical input and spectral
diagnostic where matching archived RAW exists (not a byte-reproduction target for
scanner .dat reconstruction). make run and make publish-benchmark-results refresh
archive_raw_fidelity_summary.csv, ground_truth_comparison_summary.csv, and
reconstruction_selection_summary.csv. The selection summary joins archive-RAW fidelity
with max-normalised concentration MAE; concentration MAE vs info.json concentrations is
the primary config-selection criterion.
Tri-source stage-1 parity (scanner .dat vs DICOM vs archive RAW):
make diagnose-tri-source-parity RUN_ID=<run-id> TWIX_DICOM_SERIES="E1 E6 E7 E8"Per-series stage-2 winners from a benchmark grid (scanner_dat only, backward compatible):
make grid-stage-config RUN_ID=<run-id>Source-aware quant selection (per series x input source x variant):
make benchmark-quant-grid RUN_ID=<run-id> \
BENCHMARK_SERIES="E1 E6 E7 E8" \
SCANNER_PREPROCESS_SUBSET=none,dat-b0-correct,dat-realign-full
make select-quant-config RUN_ID=<run-id> QUANT_CONFIG_APPLY=1Writes quant_config into each series info.json with independent winners for
dicom, scanner_dat, and archived_raw. stage2_default remains an alias
for the scanner_dat DIFF winner.
Benchmark-matrix runs also support an all-arm pairwise spectral consistency
matrix. make publish-benchmark-results writes pairwise_raw_summary.csv and
pairwise_raw_comparison.csv into results/<run-id>/ and spectrum plots into
runs/<run-id>/benchmark-dat-profiles/spectrum-difference-plots/.
Supported scanner preprocessing profiles include:
none: plain transient average.dat-b0-correct,dat-off-only-align,dat-water-svd-hybrid,dat-combi-ws.dat-megapress-cleanup: ECC when a water reference exists, robust registration, pair-preserving rejection, ON-to-OFF alignment, and common zero-order phase.- legacy dev profiles:
basic-align,phantom-megapress,phantom-megapress-no-ecc.
See docs/scanner-preprocessing-plan.md for the rationale and validation
sequence.
Compare preserved archive .RAW files with a generated LCModel .RAW tree:
make compare-raw-sources RUN_ID=<run-id>The comparison writes byte hashes, point counts, signal norms, complex correlations, least-squares scale factors, and residuals after rescaling.
Compare two generated RAW trees directly:
make compare-generated-raw-sources \
RUN_ID=<run-id> \
LEFT_ROOT=runs/<run-id>/benchmark-matrix/arms/dicom-none \
RIGHT_ROOT=runs/<run-id>/scanner-rawGenerated results go under runs/<run-id>/ and are ignored by git. Each run
contains LCModel inputs, controls, outputs, parsed tables, and provenance
metadata including basis and source hashes.
The canonical basis mapping is:
OFF:MEGAPRESS_edit_off_Siemens_3T.basisDIFF:MEGAPRESS_difference_Siemens_3T_kasier.basis
archive: exact preserved controls for the archived early-analysis replay (paper-archiveremains accepted as a legacy alias).archived-control: generated profile matching those archived control lines.phantom: minimal generated controls plusVITRO=T.megapress: generated MEGA-PRESS controls withSPTYPE, fit window and preliminary metabolite list.megapress-archive-refined:megapressplus the archive phase/reference constraintsSDDEGP=0andDEGPPM=0.
Exploratory controls such as sign flips, time reversal, arbitrary phase shifts, and conjugation checks are deliberately outside the release workflow. They were diagnostics, not defensible LCModel benchmark settings.
make testThe tests cover control rendering, LCModel RAW writing, basis filename mapping, scanner preprocessing, and LCModel concentration-table parsing.
This repository is licensed under AGPL-3.0-or-later and follows the REUSE
Specification. See LICENSE at the repository root. Machine-readable
copyright and license metadata is in REUSE.toml; the same license text is also
in LICENSES/AGPL-3.0-or-later.txt.