- Problem: Simulating a full EMC dictionary over many T2 values is slow (1-4 hours).
- Idea: Skip T2 points where the EMC curves change slowly, keep dense sampling where they change fast, then interpolate along T2.
- Outcome: Same fitting pipeline, faster dictionary generation. In our test: MAPE ≈ 0.01% vs. the full dictionary.
Multi-spin-echo (TSE/CPMG) trains don’t follow a simple S(t)=S0·exp(−t/T2) (as in theory) because:
- Imperfect refocusing (B1⁺ inhomogeneity / flip-angle errors) creates stimulated echoes that mix with primary echoes.
- Slice-profile & crusher schemes redistribute coherence pathways (EPG formalism), altering the apparent decay.
- Optional effects (exchange, diffusion during gradients) further deviate from a single exponential.
➡️ Therefore we use a Bloch/EPG-simulated EMC dictionary over (T2, B1⁺, …) rather than fitting a mono-exponential.
We compare the T2 map from the full dictionary to the T2 map from the interpolated dictionary.
Per-voxel percent error is:
err(i) = 100 * ( T2_interp(i) - T2_full(i) ) / T2_full(i) %
(Computed only on valid voxels: finite and > 0. DICOM values are first rescaled using RescaleSlope/Intercept.)
Reported metrics
- Pixels compared — number of voxels.
- Bias (mean %) — average signed % error. Goal: ≈ 0%.
- MAPE (mean abs %) — average abs % error. Goal: ≪ 1%.
- Median |%err| — robust central tendency. Goal: ≈ 0%.
- 95th pct |%err| — tail error; 95% of voxels are below this value. Goal: < ~1%.
Left: T2 map with the full dictionary vs. with the interpolated dictionary.
Right: Voxel-wise % error (interp vs full), display range ±1%.
Example stats:
- Pixels compared: 9,177
- Bias: 0.00% MAPE: 0.01% Median |%err|: 0.00% 95th pct |%err|: 0.00%
- Dictionary diff (relative Frobenius): 8.7e-4
-
Setup
- Clone this repo and open MATLAB.
- Add sources to the path:
addpath(genpath('src')); - Point
dicPathto your EMC dictionary (.matthat containsT2_tse_arrandecho_train_modulation).
Example:dicPath = 'data/SEMC149.mat'; % or an absolute path on your machine
-
Create an interpolated dictionary (Task 2)
- Define the banded rules (ms) and run:
rules = struct( ... 't2_min',{ 1, 81, 301}, ... 't2_max',{ 80, 300, Inf}, ... 'stride',{ 5, 10, 25}); [interpDicPath, pctSaved, keepMask] = task2_adv_interp(dicPath, rules, 'pchip');
- This writes
*_task2_interp.matnext to your source dictionary and prints the % time saved.
- Define the banded rules (ms) and run:
-
Generate T2 maps in the GUI
- Open the EMC T2 FIT GUI (per your setup).
- Load the experimental dataset.
- Run baseline with the full dictionary (B1 fit OFF, per assignment) and export the DICOM.
- change file name to 'T2_map_Full'.
- Run again with the interpolated dictionary (
interpDicPath) and export the DICOM (e.g.,...T2map_EMCt-task2_interp.dcm). - change file name to
T2_map_interpAdvanced.
-
Compare maps (voxel-wise % error)
compare_emc_t2_dicoms( ... 'path/T2_map_Full.dcm', ... 'path/T2_map_interpAdvanced.dcm');