Newer
Older
module Abstract
import ...Variables: AbstractBlock, variables, VariableType, get_pulse, get_gradient, @defvar
import ...Components: BaseComponent, InstantPulse, InstantGradient, ReadoutComponent, NoGradient, RFPulseComponent, GradientWaveform
Parent type for `BuildingBlock` or `BaseSequence`, i.e., any building block that contains other MRI components/blocks.
Iterate over them to get the individual components.
"""
abstract type ContainerBlock <: AbstractBlock end
"""
start_time(container, indices...)
Returns the start time of component with given `indices` with respect to the start of the [`ContainerBlock`](@ref).
Also see [`duration`](@ref), [`end_time`](@ref), and [`effective_time`](@ref)
"""
function start_time(container::ContainerBlock, index1, index2, indices...)
start_time(container, index1) + start_time(container[index1], index2, indices...)
end
"""
end_time(container, indices...)
Returns the start time of component with given `indices` with respect to the start of the [`ContainerBlock`](@ref).
Also see [`duration`](@ref), [`start_time`](@ref), and [`effective_time`](@ref)
"""
end_time(container::ContainerBlock, index, indices...) = start_time(container, index) + end_time(container[index], indices...)
end_time(block::AbstractBlock) = duration(block)
end_time(block::Tuple{<:VariableType, <:AbstractBlock}) = duration(block[2])
@defvar begin
effective_time(container::ContainerBlock, index, indices...) = start_time(container, index) + effective_time(container[index], indices...)
effective_time(block::Tuple{<:VariableType, <:AbstractBlock}) = block[1] + effective_time(block[2])
end
"""
effective_time(container, indices...)
Returns the start time of component with given `indices` with respect to the start of the [`ContainerBlock`](@ref).
This will crash if the component does not have an [`effective_time`](@ref) (e.g., if it is (part of) a gradient waveform).
Also see [`duration`](@ref), [`start_time`](@ref), and [`end_time`](@ref)
"""
"""
gradient_strength(sequence, time)
Returns the gradient strength at a particular time within the sequence.
"""
gradient_strength = variables.gradient_strength
Returns the RF amplitude at a particular time within the sequence in kHz.
Returns the RF phase at a particular time within the sequence in degrees.
NaN is returned if there is no pulse activate at that `time`.
"""
frequency(sequence, time)
Returns the RF frequency at a particular time within the sequence in kHz.
NaN is returned if there is no pulse activate at that `time`.
"""
"""
iter(sequence, get_type)
Helper functions for any `iter_*` functions.
"""
function iter(container::ContainerBlock, get_type::Val)
[(start_time(container, key) + t, component) for key in keys(container) for (t, component) in iter(container[key], get_type)]
end
iter(container::ContainerBlock, get_type::Symbol) = iter(container, Val(get_type))
iter(component::BaseComponent, get_type::Val) = []
iter(component::Tuple{<:Number, <:BaseComponent}, get_type::Val) = []
"""
iter_blocks(sequence)
Returns all the building blocks in the sequence with the time they will start
"""
iter_blocks(container::ContainerBlock) = iter(container, Val(:block))
"""
iter_instant_pulses(sequence)
Returns all the [`InstantPulse`](@ref) within the sequence with their timings
"""
iter_instant_pulses(container::ContainerBlock) = iter(container, Val(:instantpulse))
iter(component::Tuple{<:Number, <:InstantPulse}, ::Val{:instantpulse}) = [component]
"""
iter_instant_gradients(sequence)
Returns all the [`InstantGradient`](@ref) within the sequence with their timings
"""
iter_instant_gradients(container::ContainerBlock) = iter(container, Val(:instantgradient))
iter(component::Tuple{<:Number, <:InstantGradient}, ::Val{:instantgradient}) = [component]
"""
get_pulse(container, time)
Gets the pulse running at a particular `time` (in ms) during a sequence of building block.
If there is a RF pulse, this function will return a tuple with 2 elements:
1. The [`RFPulseComponent`](@ref) itself
2. The time since the start of the pulse
If there is no active RF pulse, `nothing` is returned.
"""
function get_pulse end
"""
get_gradient(container, time)
Gets the gradient running at a particular `time` (in ms) during a sequence of building block.
This function will return a tuple with 2 elements:
1. The [`GradientWaveform`](@ref) itself (which could be a [`NoGradient`](@ref) object).
2. The time since the start of the gradient
"""
function get_gradient end
@defvar readout_times(container::ContainerBlock) = [time for (time, _) in iter(container, Val(:readout))]
"""
readout_times(sequence)
Returns all the times that the sequence will readout.
"""
iter(component::Tuple{<:Number, <:ReadoutComponent}, ::Val{:readout}) = [(time, nothing) for time in readout_times(component[2])]