Skip to content
Snippets Groups Projects

Define variables through new @defvar macro

Merged Michiel Cottaar requested to merge new_variables into main
1 file
+ 1
1
Compare changes
  • Side-by-side
  • Inline
+ 20
18
@@ -2,7 +2,7 @@ module EPIReadouts
import ...Containers: BaseSequence, get_index_single_TR
import ..Trapezoids: Trapezoid, opposite_kspace_lines, LineReadout
import ...Components: ADC
import ...Variables: get_free_variable, VariableType, qval, qval3, set_simple_constraints!, resolution, inverse_voxel_size, inverse_fov, resolution, get_readout, apply_simple_constraint!, effective_time, voxel_size, ramp_overlap, oversample, dwell_time
import ...Variables: get_free_variable, VariableType, set_simple_constraints!, get_readout, apply_simple_constraint!, variables, @defvar
import ...Pathways: PathwayWalker, update_walker_till_time!, walk_pathway!
"""
@@ -11,16 +11,16 @@ import ...Pathways: PathwayWalker, update_walker_till_time!, walk_pathway!
Defines an (accelerated) EPI readout.
## Parameters
- [`resolution`](@ref): Resolution of the final image in the frequency- and phase-encode directions.
- [`variables.resolution`](@ref): Resolution of the final image in the frequency- and phase-encode directions.
- `recenter`: if true, the signal will be recentred in k-space after the EPI readout.
- `group`: name of the group used to rotate the readout gradients (default: :FOV).
## Variables:
- [`voxel_size`](@ref): size of the voxel in the frequency- and phase-encode directions.
- [`fov`](@ref): size of the FOV in the frequency- and phase-encode directions.
- [`ramp_overlap`](@ref): what fraction of the gradient ramp should overlap with the readout.
- [`oversample`](@ref): by how much to oversample in the frequency-encode direcion.
- [`dwell_time`](@ref): dwell time in the frequency-encode direction
- [`variables.voxel_size`](@ref): size of the voxel in the frequency- and phase-encode directions.
- [`variables.fov`](@ref): size of the FOV in the frequency- and phase-encode directions.
- [`variables.ramp_overlap`](@ref): what fraction of the gradient ramp should overlap with the readout.
- [`variables.oversample`](@ref): by how much to oversample in the frequency-encode direcion.
- [`variables.dwell_time`](@ref): dwell time in the frequency-encode direction
"""
struct EPIReadout{N} <: BaseSequence{N}
start_gradient :: Trapezoid
@@ -32,7 +32,7 @@ struct EPIReadout{N} <: BaseSequence{N}
ky_lines :: AbstractVector{<:Integer}
end
function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, group=:FOV, ky_lines=nothing, variables...)
function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, group=:FOV, ky_lines=nothing, vars...)
if length(resolution) != 2
error("EPIReadout expects the image resolution in the x- and y-direction.")
end
@@ -49,28 +49,30 @@ function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, gro
get_free_variable(nothing),
ky_lines
)
apply_simple_constraint!(qval3(res.start_gradient), VariableType[-qval(pos)/2, ky_lines[1] * res.ky_step, 0.])
apply_simple_constraint!(variables.qvec(res.start_gradient), VariableType[-variables.qvec(pos)[1]/2, ky_lines[1] * res.ky_step, 0.])
if recenter
sign = isodd(length(ky_lines)) ? -1 : 1
apply_simple_constraint!(qval3(res.recenter_gradient), VariableType[sign * qval(pos)/2, -ky_lines[end] * res.ky_step, 0.])
apply_simple_constraint!(variables.qvec(res.recenter_gradient), VariableType[sign * variables.qvec(pos)[1]/2, -ky_lines[end] * res.ky_step, 0.])
end
for shift in unique(ky_lines[2:end] - ky_lines[1:end-1])
res.blips[shift] = Trapezoid(orientation=[0, shift > 0 ? 1 : -1, 0], group=group, qval=abs(shift) * res.ky_step)
res.blips[shift] = Trapezoid(qvec=[0., shift * res.ky_step, 0.], group=group)
end
set_simple_constraints!(res, variables)
set_simple_constraints!(res, vars)
return res
end
inverse_fov(epi::EPIReadout) = [inverse_fov(epi.positive_line), 1e3 * epi.ky_step]
inverse_voxel_size(epi::EPIReadout) = [inverse_voxel_size(epi.positive_line), 1e3 * epi.ky_step * maximum(abs.(epi.ky_lines))]
resolution(epi::EPIReadout) = [resolution(epi.positive_line), maximum(abs.(epi.ky_lines))]
@defvar readout begin
inverse_fov(epi::EPIReadout) = [variables.inverse_fov(epi.positive_line), 1e3 * epi.ky_step]
inverse_voxel_size(epi::EPIReadout) = [variables.inverse_voxel_size(epi.positive_line)[1], 1e3 * epi.ky_step * maximum(abs.(epi.ky_lines))]
resolution(epi::EPIReadout) = [variables.resolution(epi.positive_line), maximum(abs.(epi.ky_lines))]
end
get_readout(epi::EPIReadout) = epi.positive_line
function effective_time(epi::EPIReadout)
@defvar function effective_time(epi::EPIReadout)
index = findfirst(iszero, epi.ky_lines)
if isnothing(index)
error("EPI readout does not pass through the centre of k-space")
end
return effective_time(epi, index * 2)
return variables.effective_time(epi, index * 2)
end
function get_index_single_TR(epi::EPIReadout, index::Integer)
@@ -101,7 +103,7 @@ function walk_pathway!(epi::EPIReadout, walker::PathwayWalker, pulse_effects::Ve
if nreadout[] > 0
return false
end
update_walker_till_time!(walker, block_start_time + effective_time(epi))
update_walker_till_time!(walker, block_start_time + variables.effective_time(epi))
return true
end
Loading