From b5ab049ca6ee8ecc84c918364d6d85b1daf33a2b Mon Sep 17 00:00:00 2001
From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk>
Date: Sat, 27 Jan 2024 18:39:06 +0000
Subject: [PATCH] Add fixed to pulses

---
 src/gradients/fixed_gradients.jl |  2 +-
 src/pulses/constant_pulses.jl    | 15 ++++++++-------
 src/pulses/fixed_pulses.jl       | 22 +++++++++++++++++++---
 src/pulses/instant_pulses.jl     | 19 ++++---------------
 src/pulses/pulses.jl             |  2 +-
 src/pulses/sinc_pulses.jl        | 10 ++++------
 6 files changed, 37 insertions(+), 33 deletions(-)

diff --git a/src/gradients/fixed_gradients.jl b/src/gradients/fixed_gradients.jl
index a1c46fe..cfe3e17 100644
--- a/src/gradients/fixed_gradients.jl
+++ b/src/gradients/fixed_gradients.jl
@@ -1,6 +1,6 @@
 module FixedGradients
 
-import ...BuildingBlock: GradientBlock
+import ...BuildingBlock: GradientBlock, fixed
 import ...Variables: variables, duration, qval
 
 
diff --git a/src/pulses/constant_pulses.jl b/src/pulses/constant_pulses.jl
index 136a1b4..15b40f3 100644
--- a/src/pulses/constant_pulses.jl
+++ b/src/pulses/constant_pulses.jl
@@ -1,9 +1,10 @@
 module ConstantPulses
 import JuMP: VariableRef, @constraint, @variable, value, Model
-import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!
+import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!, fixed
 import ...ConcreteBlocks: ConcreteBlock, to_concrete_block
 import ...Variables: variables, get_free_variable, flip_angle, phase, amplitude, frequency, bandwidth, start_time, end_time, VariableType, duration
 import ...BuildSequences: @global_model_constructor
+import ..FixedPulses: FixedPulse
 
 """
     ConstantPulse(; variables...)
@@ -46,14 +47,14 @@ bandwidth(pulse::ConstantPulse) = 3.79098854 / duration(pulse)
 
 variables(::Type{<:ConstantPulse}) = [amplitude, duration, phase, frequency, flip_angle, bandwidth]
 
-function to_concrete_block(block::ConstantPulse)
+function fixed(block::ConstantPulse)
     d = value(duration(block))
-    final_phase = value(phase(block)) + d * value(frequency(block)) * 360
-    return ConcreteBlock(value(duration(block)), pulse=[
-        ([0., d]),
+    final_phase = phase(block) + d * frequency(block) * 360
+    return FixedPulse(
+        [0., d], 
         value.([amplitude(block), amplitude(block)]),
-        value.([phase(block), final_phase])
-    ])
+        value.([phase(block), final_phase]),
+    )
 end
 
 
diff --git a/src/pulses/fixed_pulses.jl b/src/pulses/fixed_pulses.jl
index a1e1ddb..f2740fc 100644
--- a/src/pulses/fixed_pulses.jl
+++ b/src/pulses/fixed_pulses.jl
@@ -1,6 +1,6 @@
 module FixedPulses
 
-import ...BuildingBlock: PulseBlock
+import ...BuildingBlock: PulseBlock, fixed
 import ...Variables: variables, duration
 
 
@@ -32,8 +32,24 @@ end
 
 variables(::Type{<:FixedPulse}) = []
 
-duration(fg::FixedPulse) = maximum(fg.time)
+duration(fp::FixedPulse) = maximum(fp.time)
+
+Base.show(io::IO, fp::FixedPulse) = print(io, "FixedPulse for $(duration(fp)) ms")
+
+
+"""
+    FixedInstantPulse(flip_angle, phase)
+
+Fixed version of `InstantRFPulseBlock`, where both `flip_angle` and `phase` are actual numbers.
+"""
+struct FixedInstantPulse <: PulseBlock
+    flip_angle :: Number
+    phase :: Number
+end
+
+duration(fip::FixedInstantPulse) = 0.
+
+fixed(fp::Union{FixedPulse, FixedInstantPulse}) = fp
 
-Base.show(io::IO, fb::FixedPulse) = print(io, "FixedPulse for $(duration(fb)) ms")
 
 end
diff --git a/src/pulses/instant_pulses.jl b/src/pulses/instant_pulses.jl
index 0619185..8a19599 100644
--- a/src/pulses/instant_pulses.jl
+++ b/src/pulses/instant_pulses.jl
@@ -1,9 +1,10 @@
 module InstantPulses
 import JuMP: @constraint, @variable, VariableRef, value, Model
-import ...BuildingBlocks: RFPulseBlock
+import ...BuildingBlocks: RFPulseBlock, fixed
 import ...ConcreteBlocks: to_concrete_block, AbstractConcreteBlock
 import ...Variables: flip_angle, phase, start_time, variables, duration, get_free_variable, VariableType
 import ...BuildSequences: @global_model_constructor
+import ..FixedPulses: FixedInstantPulse
 
 struct InstantRFPulseBlock <: RFPulseBlock
     model :: Model
@@ -29,20 +30,8 @@ duration(instant::InstantRFPulseBlock) = 0.
 variables(::Type{<:InstantRFPulseBlock}) = [flip_angle, phase]
 
 
-"""
-    ConcreteInstantRFPulse(flip_angle, phase)
-
-Instantaneous RF pulse with no free variables.
-
-See [`InstantRFPulseBlock`](@ref) for a version where [`flip_angle`](@ref) and [`phase`](@ref) are variables.
-"""
-struct ConcreteInstantRFPulse <: AbstractConcreteBlock
-    flip_angle :: Number
-    phase :: Number
-end
-
-function to_concrete_block(block::InstantRFPulseBlock)
-    return ConcreteInstantRFPulse(value(flip_angle(block)), value(phase(block)))
+function fixed(block::InstantRFPulseBlock)
+    return FixedInstantPulse(value(flip_angle(block)), value(phase(block)))
 end
 
 end
\ No newline at end of file
diff --git a/src/pulses/pulses.jl b/src/pulses/pulses.jl
index 51db27d..8b8152e 100644
--- a/src/pulses/pulses.jl
+++ b/src/pulses/pulses.jl
@@ -4,9 +4,9 @@ include("constant_pulses.jl")
 include("sinc_pulses.jl")
 include("fixed_pulses.jl")
 
+import .FixedPulses: FixedPulse
 import .InstantPulses: InstantRFPulseBlock
 import .ConstantPulses: ConstantPulse
 import .SincPulses: SincPulse
-import .FixedPulses: FixedPulse
 
 end
\ No newline at end of file
diff --git a/src/pulses/sinc_pulses.jl b/src/pulses/sinc_pulses.jl
index 85f3bc4..78384f4 100644
--- a/src/pulses/sinc_pulses.jl
+++ b/src/pulses/sinc_pulses.jl
@@ -3,10 +3,11 @@ module SincPulses
 import JuMP: VariableRef, @constraint, @variable, value, Model
 import QuadGK: quadgk
 import Polynomials: fit, Polynomial
-import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!
+import ...BuildingBlocks: RFPulseBlock, set_simple_constraints!, fixed
 import ...ConcreteBlocks: ConcreteBlock, to_concrete_block
 import ...Variables: flip_angle, phase, amplitude, frequency, bandwidth, VariableType, variables, get_free_variable, duration
 import ...BuildSequences: @global_model_constructor
+import ..FixedPulses: FixedPulse
 
 """
     SincPulse(; symmetric=true, max_Nlobes=nothing, apodise=true, variables...)
@@ -102,15 +103,12 @@ lobe_duration(pulse::SincPulse) = pulse.lobe_duration
 bandwidth(pulse::SincPulse) = 1 / lobe_duration(pulse)
 variables(::Type{<:SincPulse}) = [amplitude, N_left, N_right, duration, phase, frequency, flip_angle, lobe_duration, bandwidth]
 
-function to_concrete_block(block::SincPulse)
+function fixed(block::SincPulse)
     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)))
     amplitudes = value(amplitude(block)) .* (normalised_function.(normed_times; apodise=block.apodise))
     phases = (value(frequency(block)) .* value(lobe_duration(block))) .* normed_times * 360
-    return ConcreteBlock(
-        value(duration(block)); 
-        pulse=(times, amplitudes, phases)
-    )
+    return FixedPulse(times, amplitudes, phases)
 end
 
 end
\ No newline at end of file
-- 
GitLab