From a74da105151bc9bb37d076a4c9cbd8894c950936 Mon Sep 17 00:00:00 2001
From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk>
Date: Wed, 31 Jan 2024 18:08:16 +0000
Subject: [PATCH] Add pulse to trapezoid to get slice selection

---
 src/overlapping/trapezoid_gradients.jl | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/src/overlapping/trapezoid_gradients.jl b/src/overlapping/trapezoid_gradients.jl
index c9f0857..a5a70fe 100644
--- a/src/overlapping/trapezoid_gradients.jl
+++ b/src/overlapping/trapezoid_gradients.jl
@@ -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
+import ...Variables: qvec, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, slice_thickness
 import ...BuildingBlocks: duration, set_simple_constraints!, fixed
 import ...BuildSequences: @global_model_constructor
 import ...Gradients: ChangingGradientBlock, ConstantGradientBlock
@@ -47,11 +47,14 @@ struct TrapezoidGradient <: AbstractOverlapping
     slew_rate :: SVector{3, VariableType}
     rotate :: Union{Nothing, Symbol}
     scale :: Union{Nothing, Symbol}
+    time_before_pulse :: VariableType
+    pulse :: Union{Nothing, Symbol}
+    time_after_pulse :: VariableType
 end
 
 @global_model_constructor TrapezoidGradient
 
-function TrapezoidGradient(model::Model; orientation=nothing, rise_time=nothing, flat_time=nothing, rotate=nothing, scale=nothing, kwargs...)
+function TrapezoidGradient(model::Model; orientation=nothing, rise_time=nothing, flat_time=nothing, rotate=nothing, scale=nothing, pulse=nothing,kwargs...)
     if isnothing(orientation) && isnothing(rotate)
         rate_1d = nothing
         slew_rate = (
@@ -82,7 +85,15 @@ function TrapezoidGradient(model::Model; orientation=nothing, rise_time=nothing,
     end
     slew_rate = SVector{3}(slew_rate)
     rise_time = get_free_variable(model, rise_time)
-    flat_time = get_free_variable(model, flat_time)
+    if isnothing(pulse)
+        flat_time = get_free_variable(model, flat_time)
+    elseif pulse isa RFPulseBlock
+        flat_time = duration(pulse)
+        time_before_pulse = time_after_pulse = 0.
+    else pulse isa Tuple
+        time_before_pulse, pulse, time_after_pulse = pulse
+        flat_time = time_before_pulse + duration(pulse) + time_after_pulse
+    end
 
     res = TrapezoidGradient(
         model,
@@ -91,7 +102,11 @@ function TrapezoidGradient(model::Model; orientation=nothing, rise_time=nothing,
         slew_rate,
         rate_1d,
         rotate,
-        scale
+        scale,
+        time_before_pulse,
+        pulse,
+        time_after_pulse
+        
     )
 
     set_simple_constraints!(model, res, kwargs)
@@ -106,7 +121,7 @@ waveform(pg::TrapezoidGradient) = [
     ChangingGradientBlock(gradient_strength(pg), -slew_rate(pg), rise_time(pg), pg.rotate, pg.scale),
 ]
 
-interruptions(pg::TrapezoidGradient) = []
+interruptions(pg::TrapezoidGradient) = isnothing(pg.pulse) ? [] : [(index=2, time=pg.time_before_pulse + effective_time(pulse), object=pg.pulse)]
 
 rise_time(pg::TrapezoidGradient) = pg.rise_time
 flat_time(pg::TrapezoidGradient) = pg.flat_time
@@ -115,6 +130,7 @@ slew_rate(g::TrapezoidGradient) = g.slew_rate
 δ(g::TrapezoidGradient) = rise_time(g) + flat_time(g)
 duration(g::TrapezoidGradient) = 2 * rise_time(g) + flat_time(g)
 qvec(g::TrapezoidGradient, ::Nothing, ::Nothing) = δ(g) .* gradient_strength(g) .* 2π
+inverse_slice_thickness(g::TrapezoidGradient) = isnothing(g.pulse) ? nothing : inverse_bandwidth(g) .* gradient_strength(g)
 
 variables(::Type{<:TrapezoidGradient}) = [qvec, δ, gradient_strength, duration, rise_time, flat_time]
 
-- 
GitLab