This project provides a comprehensive pipeline for generating synthetic weighted MRI images from quantitative multi-parameter maps (R1, R2s, PD). It allows for flexible adjustment of sequence parameters (TE, TR, FA) to simulate various image contrasts. The pipeline also includes functionality to calculate the corresponding k-space data for each coil in an MRI scanner by estimating sensitivity maps.
The core of this project is to take quantitative MRI maps (R1, R2s, PD) and generate realistic synthetic weighted images that would be produced by an MRI scanner with specific sequence parameters. This is achieved by applying the Ernst equation, which models the MRI signal intensity based on tissue properties and sequence parameters.
The main workflow is controlled by the main.m script. Here's a high-level overview of the steps:
- Setup Paths and Parameters: The
main.mscript starts by setting up the paths to the input data and defining the ranges for the sequence parameters (TE, TR, FA). - Generate Synthetic Images: The
generate_synthetic_images.mfunction is called to generate the synthetic weighted images. This function performs the following sub-steps:- Brain Extraction: If specified, it extracts the brain from the quantitative maps using either
extract_brain_bet.morextract_brain_fsl.m. - B1 Map Registration: It registers the B1 map to the quantitative maps using
register_b1_to_ref.m - Signal Calculation: It calculates the synthetic signal for each combination of TE, TR, and FA using
compute_ernst_signal.m. - Save Images: It saves the generated synthetic images as NIfTI files using
save_nifti_image.mand writes the corresponding metadata to JSON files usingwrite_json_metadata.m.
- Brain Extraction: If specified, it extracts the brain from the quantitative maps using either
- Generate B0 Maps: The
runRomeo.mfunction is called to generate B0 maps from multi-echo phase data. - Sensitivity Map Generation: If not already present, it generates sensitivity maps using
create_smaps.m. - Generate K-space Data: The
nifti_to_kspace.mfunction is called to convert the synthetic images to k-space data.- Phase evolution: Phases of synthetic images are assumed to be caused by phase portion of sensitivity maps and the B0 field inhomogenities under the assumption that phase evolves linearly with echo time.
- Calculation of per-coil images: Images are calculated for each coil seperately using respective sensitvity maps and stacked.
- Taking FFT and Saving the images: 3D FFT of each per-coil image is calculated and resulting k-space data is saved as seperate magnitude and phase NIFTI files, each with dimensions
(n_x, n_y, n_z, n_coil). - Adding Correlated Noise: Noise covariance matrix is calculated from noise scans and gaussian noise is added based on user-defined SNR.
-
Set up the environment:
- Make sure you have MATLAB installed with the Image Processing Toolbox.
- Install FSL, make sure it's in your system's PATH and it's accesible from the terminal via
FSLcommand. - Install Julia and the required packages for ROMEO (
ROMEO,MriResearchTools,ArgParse). Then install ROMEO following theinstructions in this link.
-
Configure the paths:
- Open the config.m script and modify the paths in the "Setup paths" section to point to your data.
- We adopt the folder structure of hMRI-toolbox for input directory. Your patient directory (
patient_dir) should be structured as below:
/patient_dir/ | ├── Results/ # MPMs (there should be a corresponding json file for each nifti, containing essential metadata) │ ├── <R1_filename>.nii # Must hace 'R1' in its name. │ └── <R2_filename>.nii # Must have 'R2' in its name. │ └── <PD_filename>.nii # Must have 'PD' in its name. │ │ ├── B1mapCalc/ # B1+ (RF transmit sensitivity) maps │ ├── <B1map_filename>.nii # Must have 'B1map' in its name. │ └── <B1red_filename>.nii # Anatomical reference file for coregisteration. mUst have 'B1ref' in its name. │ ├── MPMCalc/ # FOlder containing Tissue masks (GM, WM, CSF) ├── <gm_mask_filename>.m # Must hace 'c1' in its name └── <wm_mask_filename>.m # Must hace 'c2' in its name └── <csf_mask_filename>.m # Must hace 'c3' in its nameNOTE: If your input files are named differently, you can change file name patterns from create_data_struct.m
-
kspace_pathshould point to raw kspace. Pipeline is configured Siemenstwix file format with extension.dat`. It is read and mapped by mapVBVD.m. If you have the kspace data in a differetn format, consider editing the part in [create_smaps.m](./src/generation/create_smaps.m] where the data is imported. Make sure kspace is data is 3D and contains the ACS region even thoguh it is undersampled. -
im_mag_dirshould point to the directory where weighted (T1,PD etc.) magnitude images (which MPMs are created from) are stored. Directory should contain each echo in a seperate NIFTI file. Make sure length of the listreal_echo_timesprovided and number of NIFTI files inim_mag_dirmatch. -
im_phase_dirshould point to the directory where weighted (T1,PD etc.) phase images (which MPMs are created from) are stored. Directory should contain each echo in a seperate NIFTI file. Make sure length of the listreal_echo_timesprovided and number of NIFTI files inim_phase_dirmatch. -
espririt_pathshould point to the directory where the MATLAB library Matlab Library including implementations of SPIRiT, ESPIRiT, Coil Compression, SAKE. You can download the library from here. -
romeo_script_pathshould point to yourromeo.jl file. Please follow the steps in here to setup ROMEO. You can copy your file into (./ -
real_echo_timesbe a list of echo times in ms. You can find the specific echo time in your sequence configuration file. -
sequencedetermines according to which MRI sequence synthetic images will be generated. Currently, available options are GRE, MP2RAGE, FSE, FLAIR. -
TE_valuesspecifies the echo times (ms) used for generating synthetic weighted images. -
TR_valuesspecifies the repetition times (ms) for the sequence. -
FA_valueslists the flip angles (degrees) used for each acquisition. -
TI_valuesspecifies the inversion times; for MP2RAGE, values are given as pairs (first and second inversion), while for FSE they are listed individually. -
extract_brainselects the method for brain extraction (bet,tissue_maps, orno). -
interp_methodspecifies the interpolation method for resampling images. Available options aretrilinear,nearestneighbour,cubic,spline. -
threshold_tmapsets the threshold for brain extraction when using tissue probability maps. Smaller values yield larger brain outlines. -
threshold_betsets the fractional intensity threshold for BET-based brain extraction. Smaller values yield larger brain outlines. -
signal_constantis a multiplicative scaling factor applied to signal intensity to represent scanner- and sequence-dependent scaling. -
add_RF_biasdetermines whether RF sensitivity bias is reintroduced to the synthetic images (not recommended if MPMs are already bias-corrected). -
smap_params.ncalibdefines the size of the auto-calibration region (ACS) in k-space. -
smap_params.ksizesets the kernel size for ESPIRiT calibration. Larger kernels increase runtime quadratically. -
smap_params.eigThresh1is the eigenvalue threshold for selecting eigenvectors when constructing the reconstruction matrix. -
smap_params.eigThresh2is used to only select eigenvectors with eigenvalues greater than eigThresh2 for the construction of sensititvity maps. If there is multiple eigenvectors with eigenvalue greater than eigThres2, resulting sens_map will be a linear combination of those. -
smap_params.show_figurescontrols the verbosity of ESPIRiT visualizations (none,essential,detailed). -
smap_params.verbosetoggles detailed ESPIRiT console output. -
smap_params.smoothing_radiusspecifies the radius of the Gaussian smoothing kernel applied to coil sensitivity maps. -
kspace_params.fft_shiftapplies anfftshiftduring Fourier transforms. -
kspace_params.normalizenormalizes k-space data during FFT. -
kspace_params.verbosetoggles detailed console output during FFT operations. -
kspace_params.save_complexdetermines whether both magnitude and phase NIfTI files are saved (otherwise only magnitude is stored). -
noise_params.SNR_dBsets the target signal-to-noise ratio (dB). Use-1to disable noise addition. -
noise_params.add_correlated_noiseenables correlated noise simulation using covariance matrices from noise scans (otherwise uncorrelated AWGN is added). -
noise_params.num_variationsspecifies the number of synthetic noise realizations generated per weighted image.
-
Run the script:
- Run the
main.mscript in MATLAB.
- Run the
The script will then generate the synthetic images, k-space data, and B0 maps in the specified output directory.
Here is an overview of the functions in the project, with a focus on the generation pipeline.
These functions are the core of the synthetic data generation process.
generate_synthetic_images.m: Orchestrates the entire synthetic image generation workflow. It iterates through all combinations of sequence parameters (TE, TR, FA, etc.) defined inconfig.mand callscompute_ernst_signalfor each combination.compute_ernst_signal.m: The primary signal calculation engine. It computes the MRI signal intensity based on the input quantitative maps (R1, R2s, PD) and the specified sequence parameters. It supports multiple MRI sequences, including Gradient Echo (GRE), MP2RAGE, Fast Spin Echo (FSE), and FLAIR, by applying the appropriate physical signal equations for each.create_smaps.m: Computes coil sensitivity maps (smaps) from raw k-space data using the ESPIRiT algorithm. It reads a Siemens TWIX file, calibrates the k-space data, and saves the resulting sensitivity maps as both magnitude and phase NIfTI files.nifti_to_kspace.m: Converts the generated synthetic images from the image domain to the k-space domain. This process involves applying the B0 field inhomogeneity map and the previously generated coil sensitivity maps to simulate realistic, multi-coil k-space data. It performs an inverse FFT on the resulting coil images.simulate_noise.m: Adds noise to the k-space data to simulate a realistic acquisition. It can add either uncorrelated Additive White Gaussian Noise (AWGN) or correlated noise. For correlated noise, it calculates a noise covariance matrix from noise scans in the provided TWIX file. The noise level is controlled by theSNR_dBparameter inconfig.m.runRomeo.m: A wrapper script that executes the ROMEO (Robust Phase-unwrapping) algorithm. It takes multi-echo magnitude and phase images as input, merges them into 4D NIfTI files, and calls theromeo.jlJulia script to perform phase unwrapping and calculate the B0 field map.kspace_to_nifti.m: Performs the reverse operation ofnifti_to_kspace.m. It reconstructs an image from complex k-space data (magnitude and phase files) by applying a forward FFT. This is useful for validating the k-space data.
These functions prepare the input data for the generation pipeline.
extract_brain.m: A wrapper for brain extraction. It can use either FSL's BET tool (bet) or combine tissue probability maps (tissue_maps) to create a brain mask.register_b1_to_ref.m: Coregisters the B1 map to the reference quantitative maps (e.g., R1 map) to ensure they are in the same spatial alignment.resize_b1_map.m: Resizes the B1 map to match the exact matrix dimensions of the reference data, using the specified interpolation method.fixHotPixels.m: Detects and corrects extreme outlier "hot pixels" in an image, which can otherwise cause artifacts in subsequent processing steps.
main.m: The main script that drives the entire pipeline from start to finish. It loads the configuration, validates it, and calls the generation and processing functions in the correct order.config.m: The central configuration file for the project. All user-specific settings must be defined here, including paths to data, sequence parameters, and processing options.
-
create_data_struct.m: Automatically scans the input directories defined inconfig.mand creates a structured variable (data_struct) that holds the paths to all required input files (R1, PD, B1 maps, etc.). -
load_mri_data.m: Loads the actual image data and header information from the NIfTI files listed in thedata_struct. -
read_twix.m: Reads raw data from Siemens TWIX (.dat) files using themapVBVDscript. It can be used to extract k-space data or noise scan data. -
save_nifti.m: A robust function for saving NIfTI files that includes multiple fallback methods to prevent errors. -
save_nifti_image.m: A simpler wrapper function for saving NIfTI images. -
write_comprehensive_json.m: Creates detailed JSON metadata files for the generated images, including sequence parameters, processing history, and NIfTI header information. -
write_json_metadata.m: A simpler function to write essential metadata to a JSON file. -alidation Utilities -
validate_config.m: Performs a series of checks on theconfig.mfile to ensure all paths are valid and parameters are within reasonable ranges before starting the main pipeline. -
validate_mri_data.m: Checks that all required input quantitative maps (R1, R2s, PD) are present and have consistent dimensions. -
synthImageEval.m: A powerful tool for validation that compares a generated synthetic image against a ground-truth reference image. It computes several similarity metrics, including NRMSE, SSIM, Pearson correlation, and Mutual Information.
view_brain_slices.m: A simple utility to display orthogonal (axial, sagittal, coronal) views of a 3D NIfTI volume.visualize_ESPIRIT.m: Visualizes the output of the ESPIRiT algorithm, showing all individual channel images and the final root-mean-square (RMS) combined image.visualize_smap.m: Visualizes the coil sensitivity maps.
- MATLAB (with Image Processing Toolbox)
- FSL
- BART
- Julia (with
ROMEO,MriResearchTools,ArgParsepackages)
