Skip to content
Snippets Groups Projects
Verified Commit bf03ceeb authored by Michiel Cottaar's avatar Michiel Cottaar
Browse files

Allow object to self-identify as adjustable

parent f4f4e56e
No related branches found
No related tags found
No related merge requests found
module AbstractTypes
import ...Variables: AbstractBlock, duration, variables, effective_time
import ...Variables: AbstractBlock, duration, variables, effective_time, adjustable
"""
Super-type for all individual components that form an MRI sequence (i.e., RF pulse, gradient waveform, or readout event).
......@@ -49,4 +49,8 @@ It should be infinite if the component is linear.
"""
split_timestep(comp_tuple::Tuple{<:Number, <:EventComponent}, precision::Number) = split_timestep(comp_tuple[2], precision)
adjustable(::RFPulseComponent) = :pulse
adjustable(::GradientWaveform) = :gradient
end
\ No newline at end of file
module NoGradientBlocks
import StaticArrays: SVector, SMatrix
import ....Variables: VariableType, duration, qval, bmat_gradient, gradient_strength, slew_rate, get_free_variable
import ....Variables: VariableType, duration, qval, bmat_gradient, gradient_strength, slew_rate, get_free_variable, adjustable
import ...AbstractTypes: GradientWaveform
import ..ChangingGradientBlocks: split_gradient
......@@ -43,4 +43,6 @@ function split_gradient(ngb::NoGradient, times::VariableType...)
return [NoGradient(d) for d in durations]
end
adjustable(::NoGradient) = :false
end
\ No newline at end of file
......@@ -7,7 +7,7 @@ import JuMP: @constraint
import StaticArrays: SVector
import LinearAlgebra: norm
import ...Variables: qval, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, inverse_bandwidth, effective_time, qval_square, duration, set_simple_constraints!, scanner_constraints!, inverse_slice_thickness
import ...Variables: Variables, all_variables_symbols, dwell_time, inverse_fov, inverse_voxel_size, fov, voxel_size, get_gradient, get_pulse, get_readout, gradient_orientation, ramp_overlap
import ...Variables: Variables, all_variables_symbols, dwell_time, inverse_fov, inverse_voxel_size, fov, voxel_size, get_gradient, get_pulse, get_readout, gradient_orientation, ramp_overlap, adjustable, adjust_internal
import ...BuildSequences: global_model
import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent, ADC
import ...Containers: BaseBuildingBlock
......@@ -116,6 +116,36 @@ duration(g::BaseTrapezoid) = 2 * rise_time(g) + flat_time(g)
qval(g::BaseTrapezoid, ::Nothing, ::Nothing) = δ(g) .* gradient_strength(g) .* 2π
adjustable(::BaseTrapezoid) = :gradient
function adjust_internal(trap::Trapezoid1D; orientation=nothing, scale=1., rotation=nothing)
if !isnothing(orientation) && !isnothing(rotation)
error("Cannot set both the gradient orientation and rotation.")
end
new_orientation = isnothing(orientation) ? (isnothing(rotation) ? trap.orientation : rotation * trap.orientation) : orientation
return Trapezoid1D(
trap.rise_time,
trap.flat_time,
trap.slew_rate * scale,
new_orientation,
trap.group
)
end
function adjust_internal(trap::Trapezoid3D; scale=1., rotation=nothing)
return Trapezoid3D(
trap.rise_time,
trap.flat_time,
(
isnothing(rotation) ?
(trap.slew_rate .* scale) :
(rotation * (trap.slew_rate .* scale))
),
trap.group
)
end
"""
SliceSelect(pulse; orientation=nothing, group=nothing, variables...)
......
......@@ -3,7 +3,7 @@ Define post-fitting adjustments of the sequences
"""
module PostHoc
import ..Variables: AbstractBlock, adjust_internal
import ..Variables: AbstractBlock, adjust_internal, adjustable
import ..Components: GradientWaveform, RFPulseComponent, BaseComponent, NoGradient
import ..Containers: ContainerBlock
......@@ -40,12 +40,26 @@ function adjust(block::AbstractBlock; kwargs...)
res
end
function adjust_helper(container::ContainerBlock, used_names::Set{Symbol}; kwargs...)
function adjust_helper(block::AbstractBlock, used_names::Set{Symbol}; gradient=(), pulse=(), kwargs...)
params = []
for prop_name in propertynames(container)
push!(params, adjust_helper(getproperty(container, prop_name), used_names; kwargs...))
adjust_type = adjustable(block)
if adjust_type == :false
for prop_name in propertynames(block)
push!(params, adjust_helper(getproperty(block, prop_name), used_names; gradient=gradient, pulse=pulse, kwargs...))
end
return typeof(block)(params...)
else
if !isnothing(block.group) && (block.group in keys(kwargs))
push!(used_names, block.group)
return adjust_internal(block; kwargs[block.group]...)
elseif adjust_type == :gradient
push!(used_names, :gradient)
return adjust_internal(block; gradient...)
elseif adjust_type == :pulse
push!(used_names, :pulse)
return adjust_internal(block; pulse...)
end
end
return typeof(container)(params...)
end
adjust_helper(some_value, used_names::Set{Symbol}; kwargs...) = some_value
......@@ -54,29 +68,4 @@ adjust_helper(dict_variable::AbstractDict, used_names::Set{Symbol}; kwargs...) =
adjust_helper(tuple_variable::Tuple, used_names::Set{Symbol}; kwargs...) = map(tuple_variable) do v adjust_helper(v, used_names; kwargs...) end
adjust_helper(pair:: Pair, used_names::Set{Symbol}; kwargs...) = adjust_helper(pair[1], used_names; kwargs...) => adjust_helper(pair[2], used_names; kwargs...)
adjust_helper(block::NoGradient, used_names::Set{Symbol}; kwargs...) = block
function adjust_helper(block::GradientWaveform, used_names::Set{Symbol}; gradient=(), kwargs...)
if !isnothing(block.group) && (block.group in keys(kwargs))
push!(used_names, block.group)
return adjust_internal(block; kwargs[block.group]...)
else
push!(used_names, :gradient)
return adjust_internal(block; gradient...)
end
return new_block
end
function adjust_helper(block::RFPulseComponent, used_names::Set{Symbol}; pulse=(), kwargs...)
if !isnothing(block.group) && (block.group in keys(kwargs))
push!(used_names, block.group)
return adjust_internal(block; kwargs[block.group]...)
else
push!(used_names, :pulse)
return adjust_internal(block; pulse...)
end
end
adjust_helper(block::BaseComponent) = block
end
\ No newline at end of file
......@@ -40,6 +40,18 @@ This is a helper function used by [`adjust`](@ref).
"""
function adjust_internal end
"""
adjustable(block)
Returns whether a sequence, building block, or component can be adjusted
Can return one of:
- `:false`: not adjustable
- `:gradient`: expects gradient adjustment parameters
- `:pulse`: expects RF pulse adjustment parameters
"""
adjustable(::AbstractBlock) = :false
all_variables_symbols = [
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment