Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ndcn0236/mribuilder.jl
1 result
Show changes
Commits on Source (4)
...@@ -40,8 +40,8 @@ export dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, ...@@ -40,8 +40,8 @@ export dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid,
import .PostHoc: adjust, merge_sequences import .PostHoc: adjust, merge_sequences
export adjust, merge_sequences export adjust, merge_sequences
import .Sequences: GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI, MagnetisationTransfer import .Sequences: GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI, MagnetisationTransfer, MultiSpinEcho
export GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI, MagnetisationTransfer export GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI, MagnetisationTransfer, MultiSpinEcho
import .SequenceIO: read_sequence, write_sequence import .SequenceIO: read_sequence, write_sequence
export read_sequence, write_sequence export read_sequence, write_sequence
......
...@@ -134,7 +134,7 @@ function make_generic(block::SincPulse) ...@@ -134,7 +134,7 @@ function make_generic(block::SincPulse)
normed_times = -variables.N_left(block):0.1:variables.N_right(block) + 1e-5 normed_times = -variables.N_left(block):0.1:variables.N_right(block) + 1e-5
times = max.(0., (normed_times .+ variables.N_left(block))) .* variables.lobe_duration(block) times = max.(0., (normed_times .+ variables.N_left(block))) .* variables.lobe_duration(block)
amplitudes = variables.amplitude(block) .* (normalised_function.(normed_times, variables.N_left(block), variables.N_right(block); apodise=block.apodise)) amplitudes = variables.amplitude(block) .* (normalised_function.(normed_times, variables.N_left(block), variables.N_right(block); apodise=block.apodise))
phases = [variables.frequency(block) .* variables.lobe_duration(block)] .* normed_times .* 360 phases = [variables.frequency(block) .* variables.lobe_duration(block)] .* normed_times .* 360 .+ variables.phase(block)
return GenericPulse(times, amplitudes, phases, variables.effective_time(block)) return GenericPulse(times, amplitudes, phases, variables.effective_time(block))
end end
......
...@@ -182,7 +182,7 @@ function Base.getproperty(seq::T, v::Symbol) where T <: Sequence ...@@ -182,7 +182,7 @@ function Base.getproperty(seq::T, v::Symbol) where T <: Sequence
if v in [k for (k, _) in values(seq.blocks)] if v in [k for (k, _) in values(seq.blocks)]
return seq[v] return seq[v]
end end
error("Type $(T) has no field, block, or variable $(v)") error("Type $(T) has no field, block, or variable called `$(v)`")
end end
B0(sequence::Sequence) = B0(sequence.scanner) B0(sequence::Sequence) = B0(sequence.scanner)
......
module MultiSpinEchoes
import ...Containers: Sequence, start_time
import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler, refocus_pulse, Repeat
import ...Variables: get_pulse, get_readout, variables, @defvar, apply_simple_constraint!
import ...Pathways: Pathway, get_pathway
import ...BuildSequences: build_sequence
import ...Scanners: Default_Scanner
const MultiSpinEcho = Sequence{:MultiSpinEcho}
"""
SpinEcho(; echo_time, nrepeat, delay=0., excitation=(), refocus=(), readout=(), optim=(), resolution/fov/voxel_size/slice_thickness, scanner)
Defines a gradient echo sequence with a single readout event.
By default, an instant excitation and refocus pulse and readout event are used.
If image parameters are provided, this will switch to a sinc pulse and EPI readout.
## Parameters
- [`excitation`](@ref): properties of the excitation pulse as described in [`excitation_pulse`](@ref).
- [`refocus`](@ref): properties of the refocus pulse as described in [`refocus_pulse`](@ref).
- [`readout`](@ref): properties of the readout as described in [`readout_event`](@ref).
- Image parameters ([`variables.resolution`](@ref)/[`variables.fov`](@ref)/[`variables.voxel_size`](@ref)/[`variables.slice_thickness`](@ref)): describe the properties of the resulting image. See [`interpret_image_size`](@ref) for details.
- [`optim`](@ref): parameters to pass on to the Ipopt optimiser (see https://coin-or.github.io/Ipopt/OPTIONS.html).
- [`scanner`](@ref): Sets the [`Scanner`](@ref) used to constraint the gradient parameters. If not set, the [`Default_Scanner`](@ref) will be used.
## Variables
- [`variables.TE`](@ref)/[`variables.echo_time`](@ref): echo time between excitation pulse and spin echo in ms (required).
- [`variables.delay`](@ref): delay between the readout and the peak of the spin echo in ms (positive number indicates that readout is after the spin echo). Defaults to zero.
- [`variables.duration`](@ref): total duration of the sequence from start of excitation pulse to end of the final readout.
- [`variables.nrepeat`](@ref): How often to repeat the readout.
"""
function MultiSpinEcho(; excitation=(), refocus=(), readout=(), optim=(), spoiler=nothing, resolution=nothing, fov=nothing, voxel_size=nothing, slice_thickness=nothing, delay=0., scanner=Default_Scanner, vars...)
build_sequence(scanner; optim...) do
(slice_thickness, _, extra_readout_params) = interpret_image_size(fov, resolution, voxel_size, slice_thickness)
repeating_part = Sequence(Any[
:refocus => refocus_pulse(; slice_thickness=slice_thickness, refocus...),
nothing,
:readout => readout_event(; extra_readout_params..., readout...),
nothing,
])
res = Repeat(repeating_part)
seq = Sequence(Any[
:excitation => excitation_pulse(; slice_thickness=slice_thickness, excitation...),
nothing,
:repeat => res
]; name=:MultiSpinEcho, delay=delay, vars...)
apply_simple_constraint!(
(variables.effective_time(repeating_part, :refocus) + start_time(seq, :repeat) - variables.effective_time(seq, :excitation)) * 2,
variables.echo_time(seq)
)
return seq
end
end
get_pulse(se::MultiSpinEcho) = (excitation=se.excitation, refocus=se.repeat.block.refocus)
get_readout(se::MultiSpinEcho) = se.repeat.block.readout
@defvar begin
echo_time(se::MultiSpinEcho) = variables.duration(se.repeat.block)
delay(se::MultiSpinEcho) = variables.effective_time(se.repeat.block, :readout) - variables.echo_time(se)/2
nrepeat(se::MultiSpinEcho) = variables.nrepeat(se.repeat)
end
end
...@@ -3,10 +3,12 @@ include("gradient_echoes.jl") ...@@ -3,10 +3,12 @@ include("gradient_echoes.jl")
include("spin_echoes.jl") include("spin_echoes.jl")
include("diffusion_spin_echoes.jl") include("diffusion_spin_echoes.jl")
include("magnetisation_transfers.jl") include("magnetisation_transfers.jl")
include("multi_spin_echoes.jl")
import .GradientEchoes: GradientEcho import .GradientEchoes: GradientEcho
import .SpinEchoes: SpinEcho import .SpinEchoes: SpinEcho
import .DiffusionSpinEchoes: DiffusionSpinEcho, DW_SE, DWI import .DiffusionSpinEchoes: DiffusionSpinEcho, DW_SE, DWI
import .MagnetisationTransfers: MagnetisationTransfer import .MagnetisationTransfers: MagnetisationTransfer
import .MultiSpinEchoes: MultiSpinEcho
end end
\ No newline at end of file
...@@ -11,9 +11,9 @@ const SpinEcho = Sequence{:SpinEcho} ...@@ -11,9 +11,9 @@ const SpinEcho = Sequence{:SpinEcho}
""" """
SpinEcho(; echo_time, delay=0., excitation=(), refocus=(), readout=(), optim=(), resolution/fov/voxel_size/slice_thickness, scanner) SpinEcho(; echo_time, delay=0., excitation=(), refocus=(), readout=(), optim=(), resolution/fov/voxel_size/slice_thickness, scanner)
Defines a gradient echo sequence with a single readout event. Defines a spin echo sequence with a single readout event.
By default, an instant excitation pulse and readout event are used. By default, an instant excitation and refocus pulse and readout event are used.
If image parameters are provided, this will switch to a sinc pulse and EPI readout. If image parameters are provided, this will switch to a sinc pulse and EPI readout.
## Parameters ## Parameters
......