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

Add inverse_slice_thickness and better support inverse_bandwidth

parent cdcce5e9
No related branches found
No related tags found
No related merge requests found
......@@ -262,9 +262,21 @@ If set to `:min` or `:max`, minimising or maximising this function will be added
"""
function set_simple_constraints!(model::Model, block::BuildingBlock, kwargs)
to_funcs = Dict(nameof(fn) => fn for fn in variables(block))
invert_value(value::VariableType) = 1 / value
invert_value(value::Symbol) = invert_value(Val(value))
invert_value(::Val{:min}) = Val(:max)
invert_value(::Val{:max}) = Val(:min)
invert_value(value::AbstractVector) = invert_value.(value)
invert_value(value) = value
for (key, value) in kwargs
if key == :qval
apply_simple_constraint!(model, qval_square(block), value isa VariableType ? value^2 : value)
elseif key == :slice_thickness && :inverse_slice_thickness in keys(to_funcs)
apply_simple_constraint!(model, inverse_slice_thickness(block), invert_value(value))
elseif key == :bandwidth && :inverse_bandwidth in keys(to_funcs)
apply_simple_constraint!(model, inverse_bandwidth(block), invert_value(value))
else
apply_simple_constraint!(model, to_funcs[key](block), value)
end
......
......@@ -5,7 +5,7 @@ module TrapezoidGradients
import JuMP: @constraint, @variable, Model, VariableRef, owner_model, value
import StaticArrays: SVector
import ...Variables: qvec, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, slice_thickness
import ...Variables: qvec, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, inverse_slice_thickness
import ...BuildingBlocks: duration, set_simple_constraints!, fixed
import ...BuildSequences: @global_model_constructor
import ...Gradients: ChangingGradientBlock, ConstantGradientBlock
......@@ -135,7 +135,7 @@ inverse_slice_thickness(g::TrapezoidGradient) = isnothing(g.pulse) ? nothing : i
function variables(tg::TrapezoidGradient)
list = [qvec, δ, gradient_strength, duration, rise_time, flat_time]
if !isnothing(tg.pulse)
push!(list, slice_thickness)
push!(list, inverse_slice_thickness)
end
return list
end
......
module ConstantPulses
import JuMP: VariableRef, @constraint, @variable, value, Model
import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!, fixed
import ...Variables: variables, get_free_variable, flip_angle, phase, amplitude, frequency, bandwidth, start_time, end_time, VariableType, duration, effective_time, inverse_bandwidth
import ...Variables: variables, get_free_variable, flip_angle, phase, amplitude, frequency, start_time, end_time, VariableType, duration, effective_time, inverse_bandwidth
import ...BuildSequences: @global_model_constructor
import ..FixedPulses: FixedPulse
......@@ -43,10 +43,9 @@ phase(pulse::ConstantPulse) = pulse.phase
frequency(pulse::ConstantPulse) = pulse.frequency
flip_angle(pulse::ConstantPulse) = amplitude(pulse) * duration(pulse) * 360
inverse_bandwidth(pulse::ConstantPulse) = duration(pulse) / 3.79098854
bandwidth(pulse::ConstantPulse) = 1 / inverse_bandwidth(pulse)
effective_time(pulse::ConstantPulse) = duration(pulse) / 2
variables(::Type{<:ConstantPulse}) = [amplitude, duration, phase, frequency, flip_angle, bandwidth, inverse_bandwidth]
variables(::Type{<:ConstantPulse}) = [amplitude, duration, phase, frequency, flip_angle, inverse_bandwidth]
function fixed(block::ConstantPulse)
d = value(duration(block))
......
......@@ -4,7 +4,7 @@ import JuMP: VariableRef, @constraint, @variable, value, Model
import QuadGK: quadgk
import Polynomials: fit, Polynomial
import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!, fixed
import ...Variables: flip_angle, phase, amplitude, frequency, bandwidth, VariableType, variables, get_free_variable, duration, effective_time, inverse_bandwidth
import ...Variables: flip_angle, phase, amplitude, frequency, VariableType, variables, get_free_variable, duration, effective_time, inverse_bandwidth
import ...BuildSequences: @global_model_constructor
import ..FixedPulses: FixedPulse
......@@ -100,8 +100,7 @@ frequency(pulse::SincPulse) = pulse.frequency
flip_angle(pulse::SincPulse) = (pulse.nlobe_integral(N_left(pulse)) + pulse.nlobe_integral(N_right(pulse))) * amplitude(pulse) * lobe_duration(pulse) * 360
lobe_duration(pulse::SincPulse) = pulse.lobe_duration
inverse_bandwidth(pulse::SincPulse) = lobe_duration(pulse)
bandwidth(pulse::SincPulse) = 1 / inverse_bandwidth(pulse)
variables(::Type{<:SincPulse}) = [amplitude, N_left, N_right, duration, phase, frequency, flip_angle, lobe_duration, bandwidth]
variables(::Type{<:SincPulse}) = [amplitude, N_left, N_right, duration, phase, frequency, flip_angle, lobe_duration, inverse_bandwidth]
effective_time(pulse::SincPulse) = N_left(pulse) * lobe_duration(pulse)
function fixed(block::SincPulse)
......
......@@ -20,6 +20,7 @@ all_variables_symbols = [
:N_left => "The number of zero crossings of the RF pulse before the main peak",
:N_right => "The number of zero crossings of the RF pulse after the main peak",
:slice_thickness => "Slice thickness of an RF pulse that is active during a gradient.",
:inverse_bandwidth => "Inverse of the [`slice_thickness`](@ref) in 1/um.",
],
# gradients
......@@ -61,6 +62,9 @@ variables() = [values(symbol_to_func)...]
# Some universal truths
slice_thickness(bb) = inv(inverse_slice_thickness(bb))
bandwidth(bb) = inv(inverse_bandwidth(bb))
function qval_square(bb; kwargs...)
vec = qvec(bb; kwargs...)
return vec[1]^2 + vec[2]^2 + vec[3]^2
......
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