From 75155658bff35a8f298cf5f927d4ac861496db23 Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk> Date: Thu, 8 Feb 2024 14:40:10 +0000 Subject: [PATCH] Add support in walk_pathway for overlapping sequences --- src/overlapping/overlapping.jl | 2 +- src/pathways.jl | 54 +++++++++++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/overlapping/overlapping.jl b/src/overlapping/overlapping.jl index fac3a89..774aeea 100644 --- a/src/overlapping/overlapping.jl +++ b/src/overlapping/overlapping.jl @@ -4,7 +4,7 @@ include("generic.jl") include("gradient_pulses/gradient_pulses.jl") include("gradient_readouts/gradient_readouts.jl") -import .Abstract: AbstractOverlapping, interruptions, waveform +import .Abstract: AbstractOverlapping, interruptions, waveform, get_parts import .Generic: GenericOverlapping import .GradientPulses: TrapezoidGradient, SpoiltSliceSelect import .GradientReadouts: SingleLine, opposite_kspace_lines diff --git a/src/pathways.jl b/src/pathways.jl index fd2d4f2..609472b 100644 --- a/src/pathways.jl +++ b/src/pathways.jl @@ -3,9 +3,10 @@ import LinearAlgebra: norm, tr import StaticArrays: SVector, SMatrix import ..BuildingBlocks: BuildingBlock, GradientBlock, RFPulseBlock, ContainerBlock, get_children_blocks import ..Sequences: Sequence -import ..Variables: qvec, qval, bmat_gradient, VariableType, start_time, effective_time, duration +import ..Variables: qvec, qval, bmat_gradient, VariableType, start_time, effective_time, duration, qval_square import ..Wait: WaitBlock -import ..Readouts: InstantReadout +import ..Readouts: InstantReadout, ADC +import ..Overlapping: AbstractOverlapping, interruptions, waveform, get_parts """ @@ -126,6 +127,12 @@ You can set `scale` and/or `rotate` to specific symbols to only consider gradien """ qvec(pathway::Pathway; scale=nothing, rotate=nothing) = get(pathway.qvec, (scale, rotate), zero(SVector{3, Float64})) +function qval_square(pathway::Pathway; kwargs...) + vec = qvec(pathway; kwargs...) + return vec[1]^2 + vec[2]^2 + vec[3]^2 +end +qval(pathway::Pathway; kwargs...) = sqrt(qval_square(pathway; kwargs...)) + """ area_under_curve(pathway::Pathway; scale=nothing, rotate=nothing) @@ -278,7 +285,46 @@ end walk_pathway!(wait::WaitBlock, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, block_start_time=0.::VariableType) = false -function walk_pathway!(::InstantReadout, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, block_start_time=0.::VariableType) +function walk_pathway!(ao::AbstractOverlapping, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, block_start_time=0.::VariableType) + current_index = nothing + current_time = block_start_time + for (index_inter, interruption) in enumerate(interruptions(ao)) + if interruption.object isa RFPulseBlock + if iszero(length(pulse_effects)) + error("Pathway definition is invalid! Another RF pulse was encountered before the number of readouts expected from `nreadout` where detected.") + end + if pulse_effects[1] == :ignore + popfirst!(pulse_effects) + continue + end + elseif (interruption.object isa InstantReadout || interruption.object isa ADC) + if length(pulse_effects) > 0 + continue + elseif nreadout[] > 0 + nreadout[] -= 1 + continue + end + end + for part in get_parts(ao, current_index, index_inter) + update_walker_gradient!(part, walker, current_time) + current_time = current_time + duration(part) + end + if interruption.object isa RFPulseBlock + update_walker_pulse!(walker, pulse_effects, current_time) + end + current_index = index_inter + if length(pulse_effects) == 0 && nreadout[] == 0 + return true + end + end + for part in get_parts(ao, current_index, nothing) + update_walker_gradient!(part, walker, current_time) + current_time = current_time + duration(part) + end + return false +end + +function walk_pathway!(::Union{InstantReadout, ADC}, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, block_start_time=0.::VariableType) if length(pulse_effects) > 0 return false end @@ -405,7 +451,7 @@ The following steps will be taken: - update the appropriate `walker.qvec` and `walker.bmat` based on the gradient waveform. This will require appropriate `qvec`/`bmat` functions to be defined for the gradient building block. - update `walker.last_gradient_time` to the time at the end of the gradient. -This requires [`bmat`](@ref) and [`qvec`](@ref) to be implemented for the [`GradientBlock`](@ref). +This requires [`bmat_gradient`](@ref) and [`qvec`](@ref) to be implemented for the [`GradientBlock`](@ref). """ function update_walker_gradient!(gradient::GradientBlock, walker::PathwayWalker, gradient_start_time::VariableType) if !walker.is_transverse -- GitLab