From ade4e941649f5ccdc7afca9315a2f33744740eaa Mon Sep 17 00:00:00 2001
From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk>
Date: Tue, 30 Jan 2024 14:18:44 +0000
Subject: [PATCH] Add walker for generic container

---
 src/pathways.jl | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/src/pathways.jl b/src/pathways.jl
index c9dad81..e9f523d 100644
--- a/src/pathways.jl
+++ b/src/pathways.jl
@@ -1,9 +1,9 @@
 module Pathways
 import LinearAlgebra: norm
 import StaticArrays: SVector, SMatrix, MVector, MMatrix
-import ..BuildingBlocks: BuildingBlock, GradientBlock, RFPulseBlock
+import ..BuildingBlocks: BuildingBlock, GradientBlock, RFPulseBlock, ContainerBlock, get_children_blocks
 import ..Containers: Sequence
-import ..Variables: qvec, qval, bmat_gradient, VariableType
+import ..Variables: qvec, qval, bmat_gradient, VariableType, start_time, effective_time
 
 
 """
@@ -58,9 +58,9 @@ struct Pathway
     bmat :: Dict{Any, SMatrix{3, 3, VariableType, 9}}
 end
 
-function Pathway(sequence::Sequence, pulse_effects::AbstractVector, readout_index::Integer)
+function Pathway(sequence::Sequence, pulse_effects::AbstractVector, readout_index::Integer=1)
     walker = PathwayWalker()
-    walk_pathway!(sequence, interpret_pulse_effects.(pulse_effects), walker, Ref(readout_index))
+    walk_pathway!(sequence, walker, interpret_pulse_effects.(pulse_effects), Ref(readout_index))
     return Pathway(
         sequence,
         pulse_effects,
@@ -256,10 +256,6 @@ PathwayWalker() = PathwayWalker(
 
 Computes the effect of a specific [`BuildingBlock`](@ref) (starting at `start_time`) on the [`PathwayWalker`](@ref).
 
-This needs to be defined for any [`ContainerBlock`](@ref) that the walker may encounter.
-
-This might be as simpla as calling [`walk_pathway!`] on all the children (i.e., for a `Sequence`).
-
 For individual pulses and gradients, the following behaviour is implemented:
 - If a pulse is encountered, call [`update_walker_pulse!`](@ref)`(walker, pulse_effects, pulse_effective_time)`
 - If a gradient is encountered, call [`update_walker_gradient!`](@ref)(gradient, walker, gradient_start_time)
@@ -270,16 +266,25 @@ This effective time can be passed on to [`update_walker_gradient!`](@ref) to all
 
 The function should return `true` if the `Pathway` has reached its end (i.e., the final readout) and `false` otherwise.
 """
-function walk_pathway!(grad::GradientBlock, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, start_time=0.::VariableType) 
-    update_walker_gradient!(grad, walker, start_time)
+function walk_pathway!(grad::GradientBlock, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, block_start_time=0.::VariableType) 
+    update_walker_gradient!(grad, walker, block_start_time)
     return false
 end
 
-function walk_pathway!(pulse::RFPulseBlock, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, start_time=0.::VariableType) 
-    update_walker_pulse(walker, pulse_effects, nreadout, start_time + effective_time(pulse))
+function walk_pathway!(pulse::RFPulseBlock, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, block_start_time=0.::VariableType) 
+    update_walker_pulse(walker, pulse_effects, nreadout, block_start_time + effective_time(pulse))
     return iszero(length(pulse_effects)) && iszero(nreadout[])
 end
 
+function walk_pathway!(container::ContainerBlock, walker::PathwayWalker, pulse_effects::Vector{Symbol}, nreadout::Ref{Int}, block_start_time=0.::VariableType)
+    for (index, child) in get_children_blocks(container)
+        if walk_pathway!(child, walker, pulse_effects, nreadout, block_start_time + start_time(container, index))
+            return true
+        end
+    end
+    return false
+end
+
 
 """
     update_walker_pulse!(walker::PathwayWalker, pulse_effects::Vector, pulse_time)
-- 
GitLab