Simple reconstruction
Description
This example describes how to perform a reconstruction of a fully acquisition acquired with the aMP2RAGECS_360 sequence.
Loading Package
using LazyArtifacts # loading data
using SEQ_BRUKER_a_MP2RAGE_CS_360
using CairoMakie # plotting
Download the datasets
if you run the literate example offline change the following line by : `MP2artifacts = artifact"MP2RAGEdata"
datadir = Main.MP2_artifacts
@info "The test data is located at $datadir."
[ Info: The test data is located at /home/runner/.julia/artifacts/04cd4c29bb9e2aeb5384fbc70a9af0e1a37ca369.
If you want to perform your own reconstruction, you can change the following line in order to point to another a bruker dataset
path_bruker = joinpath(datadir, "MP2RAGE_FULLY")
"/home/runner/.julia/artifacts/04cd4c29bb9e2aeb5384fbc70a9af0e1a37ca369/MP2RAGE_FULLY"
Perform the reconstruction
this function will perform a standard reconstruction without compressed-sensing. If your data are subsampled it will result in subsampling artifacts (blurring + noise-like)
the keyword mean_NR=true will average the images accross the number of repetition dimension before performing the MP2RAGE/T1 maps estimation. Otherwise an image/T₁ map will be generated for each Number Of Repetition (NR)
d = reconstruction_MP2RAGE(path_bruker; mean_NR=true)
Dict{Any, Any} with 7 entries:
"LUT" => Float32[93.0 0.5; 94.0 0.5; … ; 5287.0 -0.5; 5288.0 -0.5]
"params_reco" => Dict{Any, Any}(:iterations=>1, :reconSize=>(128, 128, 96)…
"params_MP2RAGE" => ParamsMP2RAGE(800.0, 2284.1, 7.0, 5000.0, 128, 7.0, 7.0)
"im_reco" => ComplexF32[113.687-120.06im -6.39107+141.334im … 35.198+4…
"T1map" => Float32[4376.0 3452.0 … 2116.0 2853.0; 3571.0 377.0 … 238…
"params_prot" => BrukerFile: /home/runner/.julia/artifacts/04cd4c29bb9e2ae…
"MP2RAGE" => Float32[-0.493312 -0.458414 … -0.244732 -0.399954; -0.465…
the result is a dictionnary with the following fields :
- "im_reco" : (x,y,z, Number of Repetition,TI) Complex
- "MP2RAGE" : (x,y,z , Number of Repetition) Float
- "T1map" : (x,y,z , Number of Repetition) Float
- "params_prot"
- "params_reco"
- "params_MP2RAGE"
im_reco corresponds to the TI₁ and TI₂ images in the complex format with 5 dimensions : (x,y,z , Number of Repetition,TI). Channels are combined during the reconstruction
We can check the results
begin
f = Figure(size=(500,400))
ax=Axis(f[1,1],title="TI₁")
h=heatmap!(ax,abs.(d["im_reco"][:,:,60,1,1]),colormap=:grays)
ax=Axis(f[1,2],title="TI₂")
h=heatmap!(ax,abs.(d["im_reco"][:,:,60,1,2]),colormap=:grays)
ax=Axis(f[2,1],title="UNIT1 / MP2RAGE")
h=heatmap!(ax,d["MP2RAGE"][:,:,60,1],colormap=:grays)
ax=Axis(f[2,2],title="T₁ map")
h=heatmap!(ax,d["T1map"][:,:,60,1],colorrange = (500,2000))
for ax in f.content # hide decoration befor adding colorbar
hidedecorations!(ax)
end
Colorbar(f[2,3],h,label = "T₁ [ms]", flip_vertical_label=true)
f
end

The Lookup table used for the reconstruction is stored in the dictionnary (LUT). First dimension is the range of T1 and the 2nd is the expected value of the MP2RAGE signal between -0.5 to 0.5.
f=Figure()
ax = Axis(f[1,1],xlabel="T₁ [ms]")
lines!(ax,d["LUT"])
f

Write results in BIDS format
Results can be written following most of the qBIDS format recommandation
subject_name = "sub_01"
dir_path = "" # directory path where the files will be create
write_bids_MP2RAGE(d,subject_name,dir_path)
which results in :
sub_01/
├─ MP2RAGE.json
└─ anat/
├─ sub_01_T1map.nii.gz
├─ sub_01_UNIT1.nii.gz
├─ sub_01_inv-1-complex_MP2RAGE.nii.gz
├─ sub_01_inv-1-mag_MP2RAGE.nii.gz
├─ sub_01_inv-1-phase_MP2RAGE.nii.gz
├─ sub_01_inv-2-complex_MP2RAGE.nii.gz
├─ sub_01_inv-2-mag_MP2RAGE.nii.gz
└─ sub_01_inv-2-phase_MP2RAGE.nii.gz
For simplicity the T₁ map is stored in the anat/ folder like the ones created by Siemens.
If you want to generate the T1 map with another tool like qMRLab the required MP2RAGE parameters are stored in the MP2RAGE.json file. In that case the data are supposed to be stored in a derivatives folder (seeqBIDS format recommandation)
This page was generated using Literate.jl.