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

Add sequence back into ConcretBlocks to fix timings

parent 9e3be17b
No related branches found
No related tags found
No related merge requests found
...@@ -50,35 +50,38 @@ ConcreteGradient(values::Tuple{<:Vector, <:Vector, <:Vector, <:Vector}) = Concre ...@@ -50,35 +50,38 @@ ConcreteGradient(values::Tuple{<:Vector, <:Vector, <:Vector, <:Vector}) = Concre
A [`BuildingBlock`](@ref) that is fully defined (i.e., there are no variables to be optimised). A [`BuildingBlock`](@ref) that is fully defined (i.e., there are no variables to be optimised).
""" """
struct ConcreteBlock <: AbstractConcreteBlock struct ConcreteBlock <: AbstractConcreteBlock
builder :: AbstractSequence
duration :: Float64 duration :: Float64
pulse :: Union{ConcreteRFPulse, Nothing} pulse :: Union{ConcreteRFPulse, Nothing}
gradient :: Union{ConcreteGradient, Nothing} gradient :: Union{ConcreteGradient, Nothing}
readout_times :: Vector{Float64} readout_times :: Vector{Float64}
end end
function ConcreteBlock(duration::Number; pulse=nothing, gradient=nothing, readout_times=Number[]) ConcreteBlock(args...; kwargs...) = BuildingBlockPlaceholder{ConcreteBlock}(args...; kwargs...)
function ConcreteBlock(builder::AbstractSequence, duration::Number; pulse=nothing, gradient=nothing, readout_times=Number[])
ConcreteBlock(builder, duration, ConcreteRFPulse(pulse), ConcreteGradient(gradient), Float64.(readout_times)) ConcreteBlock(builder, duration, ConcreteRFPulse(pulse), ConcreteGradient(gradient), Float64.(readout_times))
end end
to_block(::SequenceBuilder, concrete::AbstractConcreteBlock) = concrete
has_values(::AbstractConcreteBlock) = true has_values(::AbstractConcreteBlock) = true
duration(c::AbstractConcreteBlock) = 0. duration(c::AbstractConcreteBlock) = 0.
duration(c::ConcreteBlock) = c.duration duration(c::ConcreteBlock) = c.duration
""" """
ConcreteBlock(other_building_block) ConcreteBlock(sequence, other_building_block)
Creates a [`ConcreteBlock`](@ref) from another [`BuildingBlock`](@ref). Creates a [`ConcreteBlock`](@ref) from another [`BuildingBlock`](@ref).
This will raise an error if the other [`BuildingBlock`](@ref) has not been optimised yet. This will raise an error if the other [`BuildingBlock`](@ref) has not been optimised yet.
If it has been optimised, then [`to_concrete_block`](@ref) will be called. If it has been optimised, then [`to_concrete_block`](@ref) will be called.
""" """
function ConcreteBlock(block::BuildingBlock) function ConcreteBlock(sequence::AbstractSequence, block::BuildingBlock)
if !has_values(block) if !has_values(block)
error("Making `BuildingBlock` objects concrete is only possible after optimisation.") error("Making `BuildingBlock` objects concrete is only possible after optimisation.")
end end
return to_concrete_block(block) return to_concrete_block(sequence, block)
end end
...@@ -89,13 +92,13 @@ Internal function used to create [`ConcreteBlock`](@ref) from any [`BuildingBloc ...@@ -89,13 +92,13 @@ Internal function used to create [`ConcreteBlock`](@ref) from any [`BuildingBloc
This needs to be defined for every [`BuildingBlock`](@ref) This needs to be defined for every [`BuildingBlock`](@ref)
""" """
function to_concrete_block(cb::AbstractConcreteBlock) function to_concrete_block(sequence, cb::ConcreteBlock)
return cb return ConcreteBlock(sequence, cb.duration, cb.pulse, cb.gradient, cb.readout_times)
end end
properties(::Type{<:ConcreteBlock}) = [] properties(::Type{<:ConcreteBlock}) = []
has_values(c::ConcreteBlock) = true has_values(c::AbstractConcreteBlock) = has_values(c.builder)
""" """
...@@ -111,11 +114,15 @@ struct Sequence <: AbstractSequence ...@@ -111,11 +114,15 @@ struct Sequence <: AbstractSequence
TR :: Number TR :: Number
end end
function Sequence(seq::SequenceBuilder) function Sequence(builder::SequenceBuilder)
if !has_values(seq) if !has_values(builder)
optimize!(seq.model) optimize!(builder.model)
end
seq = Sequence(AbstractConcreteBlock[], value(TR))
for block in builder.blocks
push!(seq.blocks, ConcreteBlock(seq, block))
end end
return Sequence(ConcreteBlock.(seq.blocks), value(seq.TR)) return seq
end end
end end
\ No newline at end of file
...@@ -2,7 +2,7 @@ module InstantGradients ...@@ -2,7 +2,7 @@ module InstantGradients
import JuMP: @constraint, @variable, VariableRef import JuMP: @constraint, @variable, VariableRef
import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration
import ...SequenceBuilders: SequenceBuilder, owner_model, start_time import ...SequenceBuilders: SequenceBuilder, owner_model, start_time
import ...ConcreteBlocks: to_concrete_block, AbstractConcreteBlock import ...ConcreteBlocks: to_concrete_block, AbstractConcreteBlock, Sequence, AbstractSequence
import ..IntegrateGradients: qval, bval import ..IntegrateGradients: qval, bval
""" """
...@@ -51,12 +51,13 @@ Instantaneous MR gradient with no free variables. ...@@ -51,12 +51,13 @@ Instantaneous MR gradient with no free variables.
See [`InstantGradientBlock`](@ref) for a version where [`qval`](@ref) is variable. See [`InstantGradientBlock`](@ref) for a version where [`qval`](@ref) is variable.
""" """
struct ConcreteInstantGradient <: AbstractConcreteBlock struct ConcreteInstantGradient <: AbstractConcreteBlock
builder :: AbstractSequence
orientation :: Any orientation :: Any
qval :: Number qval :: Number
end end
function to_concrete_block(block::InstantGradientBlock) function to_concrete_block(builder::Sequence, block::InstantGradientBlock)
return ConcreteInstantGradient(block.orientation, value(qval(block))) return ConcreteInstantGradient(builder, block.orientation, value(qval(block)))
end end
......
...@@ -7,7 +7,7 @@ import JuMP: @constraint, @variable, Model, VariableRef, owner_model, value ...@@ -7,7 +7,7 @@ import JuMP: @constraint, @variable, Model, VariableRef, owner_model, value
import StaticArrays: SVector import StaticArrays: SVector
import ...BuildingBlocks: BuildingBlock, duration, properties, set_simple_constraints!, BuildingBlockPlaceholder, gradient_strength, slew_rate import ...BuildingBlocks: BuildingBlock, duration, properties, set_simple_constraints!, BuildingBlockPlaceholder, gradient_strength, slew_rate
import ...SequenceBuilders: SequenceBuilder, start_time import ...SequenceBuilders: SequenceBuilder, start_time
import ...ConcreteBlocks: ConcreteBlock, to_concrete_block import ...ConcreteBlocks: ConcreteBlock, to_concrete_block, AbstractSequence
import ..IntegrateGradients: qval, bval import ..IntegrateGradients: qval, bval
...@@ -116,7 +116,7 @@ end ...@@ -116,7 +116,7 @@ end
properties(::Type{<:PulsedGradient}) = [qval, δ, gradient_strength, duration, rise_time, flat_time, slew_rate] properties(::Type{<:PulsedGradient}) = [qval, δ, gradient_strength, duration, rise_time, flat_time, slew_rate]
function to_concrete_block(block::PulsedGradient) function to_concrete_block(s::AbstractSequence, block::PulsedGradient)
if block.orientation == :bvec if block.orientation == :bvec
rotate = true rotate = true
qvec = [value(qval(block)), 0., 0.] qvec = [value(qval(block)), 0., 0.]
...@@ -132,7 +132,7 @@ function to_concrete_block(block::PulsedGradient) ...@@ -132,7 +132,7 @@ function to_concrete_block(block::PulsedGradient)
t_start = value(start_time(block)) t_start = value(start_time(block))
t_rise = value(rise_time(block)) t_rise = value(rise_time(block))
t_d = value(δ(block)) t_d = value(δ(block))
return ConcreteBlock(t_start + t_d + t_rise, gradients=[ return ConcreteBlock(s, t_start + t_d + t_rise, gradients=[
(t_start, zeros(3)), (t_start, zeros(3)),
(t_start + t_rise, qvec), (t_start + t_rise, qvec),
(t_start + t_d, qvec), (t_start + t_d, qvec),
......
module ConstantPulses module ConstantPulses
import JuMP: VariableRef, @constraint, @variable, value import JuMP: VariableRef, @constraint, @variable, value
import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration
import ...SequenceBuilders: SequenceBuilder, owner_model, start_time, end_time import ...SequenceBuilders: SequenceBuilder, owner_model, start_time, end_time, AbstractSequence
import ...ConcreteBlocks: ConcreteBlock, to_concrete_block import ...ConcreteBlocks: ConcreteBlock, to_concrete_block
import ..Properties: flip_angle, phase, amplitude, frequency, bandwidth import ..Properties: flip_angle, phase, amplitude, frequency, bandwidth
...@@ -49,10 +49,10 @@ bandwidth(pulse::ConstantPulse) = 3.79098854 / duration(pulse) ...@@ -49,10 +49,10 @@ bandwidth(pulse::ConstantPulse) = 3.79098854 / duration(pulse)
properties(::Type{<:ConstantPulse}) = [amplitude, duration, phase, frequency, flip_angle, bandwidth] properties(::Type{<:ConstantPulse}) = [amplitude, duration, phase, frequency, flip_angle, bandwidth]
function to_concrete_block(block::ConstantPulse) function to_concrete_block(s::AbstractSequence, block::ConstantPulse)
d = value(duration(block)) d = value(duration(block))
final_phase = value(phase(block)) + d * value(frequency(block)) * 360 final_phase = value(phase(block)) + d * value(frequency(block)) * 360
return ConcreteBlock(value(duration(block)), pulse=[ return ConcreteBlock(s, value(duration(block)), pulse=[
([0., d]), ([0., d]),
value.([amplitude(block), amplitude(block)]), value.([amplitude(block), amplitude(block)]),
value.([phase(block), final_phase]) value.([phase(block), final_phase])
......
...@@ -2,7 +2,7 @@ module InstantPulses ...@@ -2,7 +2,7 @@ module InstantPulses
import JuMP: @constraint, @variable, VariableRef, value import JuMP: @constraint, @variable, VariableRef, value
import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration
import ...SequenceBuilders: SequenceBuilder, owner_model, start_time import ...SequenceBuilders: SequenceBuilder, owner_model, start_time
import ...ConcreteBlocks: to_concrete_block, AbstractConcreteBlock import ...ConcreteBlocks: to_concrete_block, AbstractConcreteBlock, Sequence, AbstractSequence
import ..Properties: flip_angle, phase import ..Properties: flip_angle, phase
struct InstantRFPulseBlock <: BuildingBlock struct InstantRFPulseBlock <: BuildingBlock
...@@ -38,12 +38,13 @@ Instantaneous RF pulse with no free variables. ...@@ -38,12 +38,13 @@ Instantaneous RF pulse with no free variables.
See [`InstantRFPulseBlock`](@ref) for a version where [`flip_angle`](@ref) and [`phase`](@ref) are variables. See [`InstantRFPulseBlock`](@ref) for a version where [`flip_angle`](@ref) and [`phase`](@ref) are variables.
""" """
struct ConcreteInstantRFPulse <: AbstractConcreteBlock struct ConcreteInstantRFPulse <: AbstractConcreteBlock
builder :: AbstractSequence
flip_angle :: Number flip_angle :: Number
phase :: Number phase :: Number
end end
function to_concrete_block(block::InstantRFPulseBlock) function to_concrete_block(builder::Sequence, block::InstantRFPulseBlock)
return ConcreteInstantRFPulse(value(flip_angle(block)), value(phase(block))) return ConcreteInstantRFPulse(builder, value(flip_angle(block)), value(phase(block)))
end end
end end
\ No newline at end of file
...@@ -4,7 +4,7 @@ import JuMP: VariableRef, @constraint, @variable, value ...@@ -4,7 +4,7 @@ import JuMP: VariableRef, @constraint, @variable, value
import QuadGK: quadgk import QuadGK: quadgk
import Polynomials: fit, Polynomial import Polynomials: fit, Polynomial
import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration import ...BuildingBlocks: BuildingBlock, properties, BuildingBlockPlaceholder, set_simple_constraints!, duration
import ...SequenceBuilders: SequenceBuilder, owner_model, start_time, end_time import ...SequenceBuilders: SequenceBuilder, owner_model, start_time, end_time, AbstractSequence
import ...ConcreteBlocks: ConcreteBlock, to_concrete_block import ...ConcreteBlocks: ConcreteBlock, to_concrete_block
import ..Properties: flip_angle, phase, amplitude, frequency, bandwidth import ..Properties: flip_angle, phase, amplitude, frequency, bandwidth
...@@ -100,13 +100,13 @@ lobe_duration(pulse::SincPulse) = pulse.lobe_duration ...@@ -100,13 +100,13 @@ lobe_duration(pulse::SincPulse) = pulse.lobe_duration
bandwidth(pulse::SincPulse) = 1 / lobe_duration(pulse) bandwidth(pulse::SincPulse) = 1 / lobe_duration(pulse)
properties(::Type{<:SincPulse}) = [amplitude, N_left, N_right, duration, phase, frequency, flip_angle, lobe_duration, bandwidth] properties(::Type{<:SincPulse}) = [amplitude, N_left, N_right, duration, phase, frequency, flip_angle, lobe_duration, bandwidth]
function to_concrete_block(block::SincPulse) function to_concrete_block(s::AbstractSequence, block::SincPulse)
normed_times = -value(N_left(block)):0.1:value(N_right(block)) + 1e-5 normed_times = -value(N_left(block)):0.1:value(N_right(block)) + 1e-5
times = ((normed_times .+ value(N_left(block))) .* value(lobe_duration(block))) times = ((normed_times .+ value(N_left(block))) .* value(lobe_duration(block)))
amplitudes = value(amplitude(block)) .* (normalised_function.(normed_times; apodise=block.apodise)) amplitudes = value(amplitude(block)) .* (normalised_function.(normed_times; apodise=block.apodise))
phases = (value(frequency(block)) .* value(lobe_duration(block))) .* normed_times * 360 phases = (value(frequency(block)) .* value(lobe_duration(block))) .* normed_times * 360
return ConcreteBlock( return ConcreteBlock(
value(duration(block)); s, value(duration(block));
pulse_amplitude=Shape(times, amplitudes), pulse_amplitude=Shape(times, amplitudes),
pulse_phase=Shape(times, phases), pulse_phase=Shape(times, phases),
) )
......
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