Skip to content

Repository files navigation

Code - MRS MEGAPRESS/PRESS LCModel Quantification Baseline

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.

Datasets and results (make quant)

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

Documentation

Results and findings:

Scope and method:

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:

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/.

Phantom benchmark internals

The phantom benchmark separates three reconstruction-source concepts, compared as make quant arms:

  • archive replay: rerun the archived early-analysis preserved LCModel .RAW inputs with the preserved LCModel controls, then compare against archive/LCM_OFF_ALL.csv and archive/LCM_DIFF_ALL.csv;
  • dicom: generate LCModel .RAW inputs directly from scanner-processed benchmark DICOM/IMA/DCM/CSV spectra;
  • scanner-dat: inventory Siemens scanner .dat inputs under the benchmark tree and convert them to LCModel .RAW with pure-Python mapvbvd.

Inputs

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-raw

The required external inputs are:

  • benchmark source tree at MRS_BENCHMARK_ROOT, containing per-series info.json (per-series metadata incl. per-sample concentrations), scanner-export sample folders, and scanner acquisitions under <SERIES>/RAW/ (usually <SERIES>/RAW/<SAMPLE>/*.dat);
  • LCModel MEGA-PRESS BASIS files at MRS_BASIS_ROOT, specifically MEGAPRESS_edit_off_Siemens_3T.basis and MEGAPRESS_difference_Siemens_3T_kasier.basis.

Optional external inputs are:

  • MRS_ARCHIVE_RAW_ROOT, only when overriding the tracked archive/raw/ directory with alternative LCModel .RAW input files. These files must match the preserved controls' FILRAW names; they are not Siemens scanner .dat files and not the benchmark <SERIES>/RAW/<SAMPLE>/ folders;
  • in-vivo / challenge datasets under external/data-* (Big GABA, ISMRM fitting challenge, WAND) for the corresponding make 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-inputs

See 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.

Install

From a source checkout:

python -m pip install -e .
mrs-megapress-lcmodel --help

From a release archive or wheel:

python -m pip install .
mrs-megapress-lcmodel check-inputs

The 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 public

Internal Cardiff/qyber users may also install internal mirrors:

mrs-megapress-lcmodel install-inputs --all-internal --mode internal

Big 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 run

Latest 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.

LCModel setup

Build LCModel from the official Provencher source zip:

make setup-lcmodel

LCModel 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/lcmodel

Workflows

The Makefile reads .env if present and uses venv/bin/python, .venv/bin/python, or python3, in that order.

List available workflow targets:

make help

Run 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-inputs

Write inventories without running LCModel:

make inventory
make inventory-scanner

Replay archived controls and compare with the historical aggregate CSVs:

make reproduce-archive

For 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-dat

Convert 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/lcmodel

The 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-megapress

The 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 3e8

This 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=1

Writes 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-raw

Result layout

Generated 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.basis
  • DIFF: MEGAPRESS_difference_Siemens_3T_kasier.basis

Supported LCModel profiles

  • archive: exact preserved controls for the archived early-analysis replay (paper-archive remains accepted as a legacy alias).
  • archived-control: generated profile matching those archived control lines.
  • phantom: minimal generated controls plus VITRO=T.
  • megapress: generated MEGA-PRESS controls with SPTYPE, fit window and preliminary metabolite list.
  • megapress-archive-refined: megapress plus the archive phase/reference constraints SDDEGP=0 and DEGPPM=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.

Tests

make test

The tests cover control rendering, LCModel RAW writing, basis filename mapping, scanner preprocessing, and LCModel concentration-table parsing.

License

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.

About

This repository contains reproducible LCModel workflows for MRS MEGAPRESS / PRESS quantification.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages