Skip to content

Commit

Permalink
Misc fixes for formatting issues on generated documentations.
Browse files Browse the repository at this point in the history
  • Loading branch information
nbwuzhe committed Jan 31, 2024
1 parent afcef98 commit 2964b03
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 64 deletions.
55 changes: 32 additions & 23 deletions docs/lit/examples/joss_demo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,23 @@ The following file, [`recon_config_joss_demo.jl`](@__REPO_ROOT_URL__/docs/lit/ex
includes general configuration for spiral reconstruction.
It is necessary to execute this file to make sure all parameters are loaded.
Sample Data that works with this script can be found [here](https://doi.org/10.5281/zenodo.7779044).
Please download, extract and set the root_project_path as the top level folder (should be something like /your/path/here/data-2, I've renamed mine to SPIDI)
Please download, extract and set the `root_project_path` as the top level folder (should be something like `/your/path/here/data`)
=#

root_project_path = "[Your/Extracted/Data/Folder]" # Root path of the data extracted from Zenodo
include("recon_config_joss_demo.jl")

plotlyjs()

# Two user defined parameters, just for this script.
reload_spiral_data = true # Set true if we need to reload raw data compulsively.
reload_girf_data = true # Set true if we need to reload GIRF data compulsively.
# Two parameters determining whether we want to reload the raw data of spiral and GIRF.
reload_spiral_data = true; # Set true if we need to reload raw data compulsively.
reload_girf_data = true; # Set true if we need to reload GIRF data compulsively.

#=
Choose Slice ([single number] OR [1,2,31,...])
Leave an empty array ([]) or remove this line to select all slices
=#
slice_choice = []
slice_choice = [];

#=
Choose which diffusion directions and averages to be processed.
Expand All @@ -68,7 +67,9 @@ is_single_interleave = isa(params_general[:scan_fullpath], String)

#=
Choose which interleave to be reconstructed.
For multi-interleave data, the range of this value is [1:num_total_interleaves].
For multi-interleave data, the range of this value is [1:num\_total\_interleaves].
For single-interleave data, it should always be set as 1; for multi-interleave data, the value set here will be used, indicating which interleaves to be merged and reconstructed.
=#
start_idx_interleave = 1;
Expand All @@ -82,7 +83,8 @@ The steps of image reconstruction starts here.
The first step in reconstruction pipeline is to calculate the off-resonance (B₀) maps `b0_map`
and coil sensitivity maps `cartesian_sensitivity` through the Cartesian reconstruction script
[cartesian_recon.jl](@__REPO_ROOT_URL__/recon/cartesian_recon.jl).
[cartesian_recon.jl](@__REPO_ROOT_URL__/recon/cartesian_recon.jl).
Ideally this script is execute once and the calculated maps are
saved into files, which are loaded for future usage to save calculation time.
This is controlled by `do_load_maps` in general parameters.
Expand All @@ -92,7 +94,6 @@ if params_general[:do_load_maps] && isfile(params_general[:b0_map_save_fullpath]
@info "Loading SENSE and B₀ maps from $(params_general[:sensitivity_save_fullpath]) and $(params_general[:b0_map_save_fullpath])"
cartesian_sensitivity = load_map(params_general[:sensitivity_save_fullpath]; do_split_phase = true)
b0_maps = load_map(params_general[:b0_map_save_fullpath])

num_slices = size(b0_maps, 3)
else
@info "Running cartesian_recon to retrieve maps (cartesian_sensitivity and b0_maps)"
Expand Down Expand Up @@ -140,13 +141,17 @@ Slice 1, Slice 2 ... Slice N Slice 1, Slice 2 ... Slice N Slice 1, Slice 2
|_________________________________ Average 1 ___________________________________| ... |___ Average N___|
Here we chose the set corresponding to the b-value = 0 images under the first average as the example.
There is a constant shift due to pre-scan data that we want to skip, which is why the data starts from `num_slices*2`.
Note that (1) The raw data file begins with a series of pre-scan profiles with a length of `num_slices*2`
and we want to skip them; (2) There is a B1 measurement data profile between each k-space readout profile
which also need to be skipped. Thus the reading of data profiles starts from `num_slices*2 + 2` with
an increment of `2`.
=#
excitation_list = collect(num_slices*2+2:2:num_slices*4) .+ diffusion_direction * num_slices * 2 .+ (idx_average - 1) * num_slices * (num_total_diffusion_directions + 1) * 2
slice_selection = excitation_list[selected_slice]

#=
#### 3.2.2 Synchronization and Merging of k-space Data and Trajectory
#### 3.2.2 Synchronizing and Merging of k-space Data and Trajectory
Since the k-space data and spiral k-space trajectories are sampled under different sampling rates
and stored in separate files, they need to be first synchronized into the frequency of k-space data
Expand All @@ -159,7 +164,7 @@ params_spiral = Dict{Symbol,Any}()
params_spiral[:recon_size] = Tuple(params_general[:recon_size])
params_spiral[:interleave] = start_idx_interleave
params_spiral[:num_samples] = params_general[:num_adc_samples]
params_spiral[:delay] = 0.00000 # naive delay correction
params_spiral[:delay] = 0.00000
params_spiral[:interleave_data_filenames] = params_general[:scan_fullpath]
params_spiral[:traj_filename] = params_general[:gradient_fullpath]
params_spiral[:excitations] = slice_selection
Expand All @@ -176,7 +181,7 @@ This step is done through the function `merge_raw_interleaves`, which can be vie
[utils.jl](@__REPO_ROOT_URL__/src/utils/utils.jl).
Since the loaded/calculated sens maps and B₀ maps are in ascending slice order,
they need to be reordered according to the slice order in the spiral RawAcqData
they need to be reordered according to the slice order in the spiral RawAcqData.
We only do these steps when they have not been done yet or it's specifically required.
=#
Expand All @@ -193,16 +198,16 @@ end
#### 3.2.3 Correction of k-space Trajectory Using Gradient Impulse Response Function
The previously calculated GIRFs are loaded.
The spiral trajectory is corrected by the 1st and 0th order of GIRF.
Finally we check if the k-space trajectory is normalized to the range [-0.5, 0.5].
=#

#Load GIRFs (K1)
#Correct trajectory with the first order GIRFs (K1)
girf_k1 = readGIRFFile(params_general[:girf_fullpath][1], params_general[:girf_fullpath][2], params_general[:girf_fullpath][3], "GIRF_FT", false)
girf_applier_k1 = GirfApplier(girf_k1, params_general[:gamma])

#Load K0 GIRF
#Correct trajectory with the zeroth order GIRFs (K0)
girf_k0 = readGIRFFile(params_general[:girf_fullpath][1], params_general[:girf_fullpath][2], params_general[:girf_fullpath][3], "b0ec_FT", true)
girf_applier_k0 = GirfApplier(girf_k0, params_general[:gamma])

Expand All @@ -216,7 +221,7 @@ if params_general[:do_correct_with_girf_k0]
apply_k0!(imaging_acq_data, girf_applier_k0)
end

# Check the k-space nodes so they don't exceed frequency limits [-0.5, 0.5]
# Check if the k-space trajectory is normalized to the range `[-0.5, 0.5]`.
check_acquisition_nodes!(imaging_acq_data)

#=
Expand All @@ -243,7 +248,7 @@ if params_general[:do_plot_recon]
plot_sense_maps(sensitivity,20)
end

# Do coil compression to make recon faster
# Optional: Coil compression to further reduce the time of recon
if params_general[:do_coil_compression]
imaging_acq_data, sensitivity = geometricCC_2d(imaging_acq_data, sensitivity, params_general[:num_virtual_coils])
end
Expand All @@ -252,18 +257,21 @@ end
#### 3.2.6 Processing Off-Resonance (B₀) Maps
We need to resize the B₀ maps to the size of output encoding matrix size.
=#
resized_b0_maps = mapslices(x -> imresize(x, params_spiral[:recon_size][1], params_spiral[:recon_size][2]), b0_maps, dims = [1, 2])

#=
#### 3.2.7 Alignment of Off-Resonance, Sensitivity, and Spiral Data
We need to make sure that the axes line up so we rotate the sensitivities and the off-resonance maps
We need to make sure that the axes line up so we rotate the sensitivities and the off-resonance maps.
Depending on your geometry, this might not be necessary but in case you need them:
```
resized_b0_maps = mapslices(x->rotl90(x),resized_b0_maps,dims=[1,2])
sensitivity = mapslices(x->rotl90(x),sensitivity,dims=[1,2])
```
=#

#=
Expand Down Expand Up @@ -300,9 +308,9 @@ to perform final spiral image reconstruction.
@info "Performing Spiral Reconstruction"
@time reco = reconstruction(imaging_acq_data, params_recon)

GC.gc() # Recommended to use especially when encountering memory issue due to improper garbage collection.
GC.gc() # Recommended to force triger garbage collection especially when encountering memory issues.

# Reorder slices to an ascending order
# Reorder slices of the reconstructed images to an ascending order
reco = reco[:,:,slice_idx_array_spiral[selected_slice]]
resized_b0_maps = resized_b0_maps[:, :, slice_idx_array_spiral[selected_slice]]

Expand All @@ -314,7 +322,8 @@ and be plotted using the `plot_reconstruction` function, both located in
the file [utils.jl](@__REPO_ROOT_URL__/src/utils/utils.jl).
=#
if params_general[:do_save_recon] # TODO: include elements to save as tuple, e.g., ["b0", "sense", "recon"], same for load

if params_general[:do_save_recon]
resolution_tmp = fieldOfView(imaging_acq_data)[1:2] ./ encodingSize(imaging_acq_data)
resolution_mm = (resolution_tmp[1], resolution_tmp[2], fieldOfView(imaging_acq_data)[3] * (1 + params_general[:slice_distance_factor_percent] / 100.0)) #for 2D only, since FOV[3] is slice thickness then, but gap has to be observed
num_slices = numSlices(imaging_acq_data)
Expand Down
Loading

0 comments on commit 2964b03

Please sign in to comment.