Skip to content

Commit

Permalink
update all
Browse files Browse the repository at this point in the history
  • Loading branch information
aTrotier committed Nov 12, 2024
1 parent f5ca05a commit 42a9cff
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 33 deletions.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,27 @@ You can install the package in any project with the following command :
- enter the Julia package manager by typing `]` in the REPL. (the REPL should turn in blue)
- if you want to activate an environment, type : `activate .` (otherwise the package will be installed in the global environment)
- In order to add our unregistered package, type `add https://github.com/CRMSB/SEQ_BRUKER_a_MP2RAGE_CS_360`
- if you want to use the package : `using SEQ_BRUKER_a_MP2RAGE_CS_360`
- if you want to use the package in your script just add the following line : `using SEQ_BRUKER_a_MP2RAGE_CS_360`

## How to use the package

Follow the example in the [documentation](https://crmsb.github.io/SEQ_BRUKER_a_MP2RAGE_CS_360/dev/generated/examples/simple_reco/)

**Steps :**
- Define the path to the bruker dataset
```julia
path_bruker = joinpath(datadir, "MP2RAGE_FULLY")
```
- Perform the reconstruction
```julia
d = reconstruction_MP2RAGE(path_bruker; mean_NR=true)
```
- write the results in the qBIDS format
```julia
subject_name = "sub_01"
dir_path = "" # directory path where the files will be create
write_bids_MP2RAGE(d,subject_name,dir_path)
```

## Version

Expand Down
21 changes: 9 additions & 12 deletions docs/lit/examples/advanced_reco.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ using SEQ_BRUKER_a_MP2RAGE_CS_360
using CairoMakie # plotting

# In addition we load the package internally used to perform the reconstruction
using SEQ_BRUKER_a_MP2RAGE_CS_360.MRIReco
using SEQ_BRUKER_a_MP2RAGE_CS_360.MRIReco.RegularizedLeastSquares



# ## 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 : `MP2_artifacts = artifact"MP2RAGE_data"
datadir = Main.MP2_artifacts
@info "The test data is located at $datadir."

Expand All @@ -28,8 +26,7 @@ path_bruker = joinpath(datadir, "MP2RAGE_CS2")

# ## Compressed-sensing reconstruction
# In order to use an advanced reconstruction we will pass some parameters that will be used by the reconstruction package MRIReco.jl
using SEQ_BRUKER_a_MP2RAGE_CS_360.MRIReco
using SEQ_BRUKER_a_MP2RAGE_CS_360.MRIReco.RegularizedLeastSquares


# We have to create a parameter dictionnary that will be used. If you need more information about it take a look at [MRIReco.jl](https://github.com/MagneticResonanceImaging/MRIReco.jl)

Expand All @@ -41,7 +38,7 @@ CS[:iterations] = 30

d = reconstruction_MP2RAGE(path_bruker; mean_NR=true,paramsCS = CS)

# for comparison purpose let's perform the undersampled reconstruction (without the paramCS keyword)
# for comparison purposes let's perform the undersampled reconstruction (without the paramCS keyword)
d_under = reconstruction_MP2RAGE(path_bruker; mean_NR=true)


Expand All @@ -56,10 +53,10 @@ begin
h=heatmap!(ax,abs.(d["im_reco"][:,:,60,1,1,1]),colormap=:grays)


ax=Axis(f[2,1],title="UNIT1 undersampled")
ax=Axis(f[2,1],title="T₁ map undersampled")
h=heatmap!(ax,d_under["T1map"][:,:,60,1,1],colorrange = (500,2000))

ax=Axis(f[2,2],title="UNIT1 CS")
ax=Axis(f[2,2],title="T₁ map CS")
h=heatmap!(ax,d["T1map"][:,:,60,1,1],colorrange = (500,2000))

for ax in f.content # hide decoration befor adding colorbar
Expand All @@ -77,4 +74,4 @@ end

subject_name = "sub_01_cs"
dir_path = "" # directory path where the files will be create
write_bids_MP2RAGE(d,subject_name,dir_path)
write_bids_MP2RAGE(d,subject_name,dir_path)
28 changes: 15 additions & 13 deletions docs/lit/examples/simple_reco.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,31 @@ 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 : `MP2_artifacts = artifact"MP2RAGE_data"
datadir = Main.MP2_artifacts
@info "The test data is located at $datadir."

# 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")

# ## Perform the reconstruction
# this function will perform a standard reconstruction without compressed-sensing. If your data are subsampled, results will be undersampled 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 image before performing the MP2RAGE/T1 maps estimation.
# 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)


# the result is a dictionnary with the following fields :
# - "im_reco" : (x,y,z,Number of Repetition,TI) Complex
# - "MP2RAGE" : (x,y,z,TI) Float
# - "T1map" : (x,y,z,Number of Repetition) Float
# - "im_reco" : (x,y,z,Number of Channel , Number of Repetition,TI) Complex
# - "MP2RAGE" : (x,y,z,Number of Channel , Number of Repetition) Float
# - "T1map" : (x,y,z,Number of Channel , Number of Repetition) Float
# - "params_prot"
# - "params_reco"
# - "params_MP2RAGE"
#
# im_reco corresponds to the TI₁ and \TI₂ images in the complex format with 6 dimensions :
# (x,y,z,Number of Repetition,TI)
# im_reco corresponds to the TI₁ and TI₂ images in the complex format with 6 dimensions :
# (x,y,z, Number of Channel , Number of Repetition,TI)


# We can check the results
Expand All @@ -53,7 +53,7 @@ begin
ax=Axis(f[2,1],title="UNIT1 / MP2RAGE")
h=heatmap!(ax,d["MP2RAGE"][:,:,60,1,1],colormap=:grays)

ax=Axis(f[2,2],title="UNIT1 / MP2RAGE")
ax=Axis(f[2,2],title="T₁ map")
h=heatmap!(ax,d["T1map"][:,:,60,1,1],colorrange = (500,2000))

for ax in f.content # hide decoration befor adding colorbar
Expand All @@ -64,8 +64,8 @@ begin
f
end

# The Lookup table used for the reconstruction is stored in the dictionnary (LUT)
# First columns is the range of T1.
# 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"])
Expand Down Expand Up @@ -94,7 +94,9 @@ sub_01/
└─ sub_01_inv-2-phase_MP2RAGE.nii.gz
```
If you want to generate the T1 map with another tools like qMRLab
the required MP2RAGE parameters are stored in the **MP2RAGE.json** file.
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 (see[qBIDS format recommandation](https://bids-specification.readthedocs.io/en/stable/appendices/qmri.html))
=#

1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ makedocs(;
"Home" => "index.md",
"Examples" =>["generated/examples/simple_reco.md",
"generated/examples/advanced_reco.md"],
"API" => "api.md"
],
)

Expand Down
11 changes: 6 additions & 5 deletions src/BIDS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ This function writes data from a dictionary (`d`) in BIDS (Brain Imaging Data St
**Arguments:**
* `d` (Dict): A dictionary containing the data to be written. Expected keys:
* `d` (Dict): A dictionary containing the data to be written. Expected key-value pairs:
* `im_reco` (Array): 5D array containing the reconstructed images.
* `MP2RAGE` (Array): T1 map image.
* `T1maps` (Array): Additional T1 map data (optional).
* `params_prot` (Dict): Dictionary containing acquisition parameters.
* `params_MP2RAGE` (Dict): Dictionary containing MP2RAGE specific parameters.
* `MP2RAGE` (Array): Combined MP2RAGE image data.
* `T1map` (Array): Calculated T1 map from MP2RAGE images.
* `params_prot` (Dict): Protocol parameters extracted from the Bruker file.
* `params_MP2RAGE` (Struct): Dictionary containing MP2RAGE specific parameters.
* `subname` (AbstractString): The name of the subject.
* `folder` (AbstractString, optional): The folder where the BIDS data will be written. Defaults to the current directory.
Expand Down
2 changes: 1 addition & 1 deletion src/bruker_sequence.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export RawAcquisitionData_MP2RAGE
"""
RawAcquisitionData_MP2RAGE(b::BrukerFile)
Convert a Bruker dataset acquired with the a_MP2RAGE_CS_360 sequence into a
Convert a Bruker dataset acquired with the a\\_MP2RAGE\\_CS\\_360 sequence into a
`RawAcquisitionData` object compatible with the MRIReco functions.
Input :
Expand Down
50 changes: 49 additions & 1 deletion src/reconstruction.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,41 @@
export reconstruction_MP2RAGE
export reconstruction_MP2RAGE, params_from_seq

"""
reconstruction_MP2RAGE(path_bruker::String; mean_NR::Bool = false, paramsCS::Dict = Dict())
Reconstructs MP2RAGE MRI data from a specified Bruker file path, returning images and T1 maps.
# Arguments
- `path_bruker::String`: Path to the Bruker file containing MRI acquisition data.
- `mean_NR::Bool`: If `true`, calculates the mean of the reconstructed data accross the repetition (default: `false`).
- `paramsCS::Dict`: Optional dictionary for customizing reconstruction parameters. These values override the default parameter dictionary (`params`).
# Returns
A dictionary with the following key-value pairs:
- `"im_reco"`: Reconstructed MP2RAGE image array, permuted to match the expected order.
- `"MP2RAGE"`: Combined MP2RAGE image data.
- `"T1map"`: Calculated T1 map from MP2RAGE images.
- `"params_reco"`: Dictionary of parameters used for reconstruction.
- `"params_MP2RAGE"`: Sequence parameters derived from the Bruker file.
- `"params_prot"`: Protocol parameters extracted from the Bruker file.
- `"LUT"`: Lookup table with T1 range and associated values.
# Description
The function performs the following steps:
1. Reads acquisition data from the Bruker file at `path_bruker`.
2. Constructs calibration data using an ESPIRiT sensitivity map from low-resolution data.
3. Sets reconstruction parameters, allowing for custom parameters specified in `paramsCS`.
4. Reconstructs the MP2RAGE image data and optionally averages across repeated measurements.
5. Permutes the resulting array dimensions for compatibility.
6. Extracts T1 maps from MP2RAGE images and constructs a lookup table (`LUT`).
# Example
```julia
d = reconstruction_MP2RAGE("path/to/bruker_data", mean_NR = true, paramsCS = Dict(:iterations => 5))
println(d["T1map"])
```
"""

function reconstruction_MP2RAGE(path_bruker;mean_NR::Bool = false,paramsCS=Dict())
b = BrukerFile(path_bruker)
Expand Down Expand Up @@ -45,6 +82,17 @@ function reconstruction_MP2RAGE(path_bruker;mean_NR::Bool = false,paramsCS=Dict(
return d
end

"""
params_from_seq(b::BrukerFile)
Extracts MP2RAGE sequence parameters from a Bruker file and returns them in a `ParamsMP2RAGE` structure.
# Arguments
- `b::BrukerFile`: Bruker file containing sequence parameter information.
# Returns
A `ParamsMP2RAGE` structure containing key sequence timings and settings for MP2RAGE reconstruction.
"""
function params_from_seq(b::BrukerFile)
return ParamsMP2RAGE(
parse(Float64,b["EffectiveTI"][1]),
Expand Down

0 comments on commit 42a9cff

Please sign in to comment.