From 9c8404a059b923cd475d9d35144f6c3153711303 Mon Sep 17 00:00:00 2001
From: Michiel Cottaar <MichielCottaar@protonmail.com>
Date: Fri, 24 May 2024 16:06:16 +0100
Subject: [PATCH] Update code to use @defvar

---
 src/MRIBuilder.jl                      | 36 +++++++++++++-------------
 src/parts/epi_readouts.jl              | 20 +++++++-------
 src/parts/helper_functions.jl          |  2 +-
 src/parts/slice_select_rephases.jl     |  4 +--
 src/parts/spoilt_slice_selects.jl      | 29 ++++++++++++---------
 src/parts/trapezoids.jl                | 33 ++++++++++++-----------
 src/plot.jl                            | 24 ++++++++---------
 src/printing.jl                        | 13 +++-------
 src/sequence_io/pulseq.jl              |  6 ++---
 src/sequences/diffusion_spin_echoes.jl | 11 +++++---
 src/sequences/gradient_echoes.jl       |  4 +--
 src/sequences/spin_echoes.jl           |  9 ++++---
 12 files changed, 100 insertions(+), 91 deletions(-)

diff --git a/src/MRIBuilder.jl b/src/MRIBuilder.jl
index ae8cbbb..2837b2d 100644
--- a/src/MRIBuilder.jl
+++ b/src/MRIBuilder.jl
@@ -9,12 +9,12 @@ include("variables.jl")
 include("components/components.jl")
 include("containers/containers.jl")
 include("pathways.jl")
-#include("parts/parts.jl")
-#include("post_hoc.jl")
-#include("sequences/sequences.jl")
-#include("printing.jl")
-#include("sequence_io/sequence_io.jl")
-#include("plot.jl")
+include("parts/parts.jl")
+include("post_hoc.jl")
+include("sequences/sequences.jl")
+include("printing.jl")
+include("sequence_io/sequence_io.jl")
+include("plot.jl")
 
 import .BuildSequences: build_sequence, global_model, global_scanner, fixed
 export build_sequence, global_model, global_scanner, fixed
@@ -34,22 +34,22 @@ export ContainerBlock, start_time, end_time, waveform, waveform_sequence, events
 import .Pathways: Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway
 export Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway
 
-#import .Parts: dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size
-#export dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size
+import .Parts: dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size
+export dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size
 
-#import .PostHoc: adjust, merge_sequences
-#export adjust, merge_sequences
+import .PostHoc: adjust, merge_sequences
+export adjust, merge_sequences
 
-#import .Sequences: GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI
-#export GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI
+import .Sequences: GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI
+export GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI
 
-#import .SequenceIO: read_sequence, write_sequence
-#export read_sequence, write_sequence
+import .SequenceIO: read_sequence, write_sequence
+export read_sequence, write_sequence
 
-#import .Plot: plot_sequence
-#export plot_sequence
+import .Plot: plot_sequence
+export plot_sequence
 
-#import JuMP: @constraint, @objective, objective_function, value, Model
-#export @constraint, @objective, objective_function, value, Model
+import JuMP: @constraint, @objective, objective_function, value, Model
+export @constraint, @objective, objective_function, value, Model
 
 end
diff --git a/src/parts/epi_readouts.jl b/src/parts/epi_readouts.jl
index dcd068e..92fb34c 100644
--- a/src/parts/epi_readouts.jl
+++ b/src/parts/epi_readouts.jl
@@ -2,7 +2,7 @@ module EPIReadouts
 import ...Containers: BaseSequence, get_index_single_TR
 import ..Trapezoids: Trapezoid, opposite_kspace_lines, LineReadout
 import ...Components: ADC
-import ...Variables: get_free_variable, VariableType, qval, qval3, set_simple_constraints!, resolution, inverse_voxel_size, inverse_fov, resolution, get_readout, apply_simple_constraint!, effective_time, voxel_size, ramp_overlap, oversample, dwell_time
+import ...Variables: get_free_variable, VariableType, set_simple_constraints!, get_readout, apply_simple_constraint!, variables, @defvar
 import ...Pathways: PathwayWalker, update_walker_till_time!, walk_pathway!
 
 """
@@ -49,10 +49,10 @@ function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, gro
         get_free_variable(nothing),
         ky_lines
     )
-    apply_simple_constraint!(qval3(res.start_gradient), VariableType[-qval(pos)/2, ky_lines[1] * res.ky_step, 0.])
+    apply_simple_constraint!(variables.qval3(res.start_gradient), VariableType[-variables.qval(pos)/2, ky_lines[1] * res.ky_step, 0.])
     if recenter
         sign = isodd(length(ky_lines)) ? -1 : 1
-        apply_simple_constraint!(qval3(res.recenter_gradient), VariableType[sign * qval(pos)/2, -ky_lines[end] * res.ky_step, 0.])
+        apply_simple_constraint!(variables.qval3(res.recenter_gradient), VariableType[sign * variables.qval(pos)/2, -ky_lines[end] * res.ky_step, 0.])
     end
     for shift in unique(ky_lines[2:end] - ky_lines[1:end-1])
         res.blips[shift] = Trapezoid(orientation=[0, shift > 0 ? 1 : -1, 0], group=group, qval=abs(shift) * res.ky_step)
@@ -61,16 +61,18 @@ function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, gro
     return res
 end
 
-inverse_fov(epi::EPIReadout) = [inverse_fov(epi.positive_line), 1e3 * epi.ky_step]
-inverse_voxel_size(epi::EPIReadout) = [inverse_voxel_size(epi.positive_line), 1e3 * epi.ky_step * maximum(abs.(epi.ky_lines))]
-resolution(epi::EPIReadout) = [resolution(epi.positive_line), maximum(abs.(epi.ky_lines))]
+@defvar begin
+    inverse_fov(epi::EPIReadout) = [variables.inverse_fov(epi.positive_line), 1e3 * epi.ky_step]
+    inverse_voxel_size(epi::EPIReadout) = [variables.inverse_voxel_size(epi.positive_line), 1e3 * epi.ky_step * maximum(abs.(epi.ky_lines))]
+    resolution(epi::EPIReadout) = [variables.resolution(epi.positive_line), maximum(abs.(epi.ky_lines))]
+end
 get_readout(epi::EPIReadout) = epi.positive_line
-function effective_time(epi::EPIReadout)
+@defvar function effective_time(epi::EPIReadout)
     index = findfirst(iszero, epi.ky_lines)
     if isnothing(index)
         error("EPI readout does not pass through the centre of k-space")
     end
-    return effective_time(epi, index * 2)
+    return variables.effective_time(epi, index * 2)
 end
 
 function get_index_single_TR(epi::EPIReadout, index::Integer)
@@ -101,7 +103,7 @@ function walk_pathway!(epi::EPIReadout, walker::PathwayWalker, pulse_effects::Ve
     if nreadout[] > 0
         return false
     end
-    update_walker_till_time!(walker, block_start_time + effective_time(epi))
+    update_walker_till_time!(walker, block_start_time + variables.effective_time(epi))
     return true
 end
 
diff --git a/src/parts/helper_functions.jl b/src/parts/helper_functions.jl
index 67dd765..927a226 100644
--- a/src/parts/helper_functions.jl
+++ b/src/parts/helper_functions.jl
@@ -8,7 +8,7 @@ import ..EPIReadouts: EPIReadout
 import ...BuildSequences: global_model, build_sequence, global_scanner
 import ...Containers: Sequence
 import ...Components: SincPulse, ConstantPulse, InstantPulse, SingleReadout, InstantGradient
-import ...Variables: qvec, flat_time, rise_time, qval, apply_simple_constraint!, variables
+import ...Variables: variables
 
 
 function _get_pulse(shape, flip_angle, phase, frequency, Nzeros, group, bandwidth, duration)
diff --git a/src/parts/slice_select_rephases.jl b/src/parts/slice_select_rephases.jl
index 397113e..5f291cb 100644
--- a/src/parts/slice_select_rephases.jl
+++ b/src/parts/slice_select_rephases.jl
@@ -1,7 +1,7 @@
 module SliceSelectRephases
 import ...Containers: BaseSequence, get_index_single_TR
 import ..Trapezoids: SliceSelect, Trapezoid
-import ...Variables: get_pulse, qval, apply_simple_constraint!, effective_time
+import ...Variables: get_pulse, apply_simple_constraint!, variables, @defvar
 import ...Components: RFPulseComponent
 
 """
@@ -34,6 +34,6 @@ end
 get_index_single_TR(ss::SliceSelectRephase, ::Val{1}) = ss.slice_select
 get_index_single_TR(ss::SliceSelectRephase, ::Val{2}) = ss.rephase
 get_pulse(ssr::SliceSelectRephase) = ssr.slice_select
-effective_time(ssr::SliceSelectRephase) = effective_time(ssr, 1)
+@defvar effective_time(ssr::SliceSelectRephase) = variables.effective_time(ssr, 1)
 
 end
\ No newline at end of file
diff --git a/src/parts/spoilt_slice_selects.jl b/src/parts/spoilt_slice_selects.jl
index 34aefd3..ebaa4e3 100644
--- a/src/parts/spoilt_slice_selects.jl
+++ b/src/parts/spoilt_slice_selects.jl
@@ -4,7 +4,7 @@ import LinearAlgebra: norm
 import StaticArrays: SVector
 import JuMP: @constraint, @objective, objective_function
 import ...BuildSequences: global_model, global_scanner
-import ...Variables: VariableType, duration, rise_time, flat_time, effective_time, qval, gradient_strength, slew_rate, inverse_slice_thickness, get_free_variable, get_pulse, set_simple_constraints!, gradient_orientation
+import ...Variables: VariableType, get_pulse, set_simple_constraints!, variables, @defvar
 import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent
 import ...Containers: BaseBuildingBlock
 
@@ -92,9 +92,11 @@ function SpoiltSliceSelect(pulse::RFPulseComponent; orientation=[0, 0, 1], group
     return res
 end
 
-gradient_orientation(spoilt::SpoiltSliceSelect) = spoilt.orientation
-duration_trap1(spoilt::SpoiltSliceSelect) = 2 * spoilt.rise_time1 + spoilt.flat_time1 - spoilt.diff_time
-duration_trap2(spoilt::SpoiltSliceSelect) = 2 * spoilt.fall_time2 + spoilt.flat_time2 - spoilt.diff_time
+@defvar begin
+    gradient_orientation(spoilt::SpoiltSliceSelect) = spoilt.orientation
+    duration_trap1(spoilt::SpoiltSliceSelect) = 2 * spoilt.rise_time1 + spoilt.flat_time1 - spoilt.diff_time
+    duration_trap2(spoilt::SpoiltSliceSelect) = 2 * spoilt.fall_time2 + spoilt.flat_time2 - spoilt.diff_time
+end
 
 Base.keys(::SpoiltSliceSelect) = Val.((:rise1, :flat1, :fall1, :flat_pulse, :pulse, :rise2, :flat2, :fall2))
 Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:rise1}) = ChangingGradient(0., slew_rate(spoilt), gradient_orientation(spoilt), rise_time(spoilt)[1], spoilt.group)
@@ -106,16 +108,19 @@ Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:rise2}) = ChangingGradient(slew_
 Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:flat2}) = ConstantGradient(slew_rate(spoilt) * fall_time(spoilt)[2], gradient_orientation(spoilt), flat_time(spoilt)[2], spoilt.group)
 Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:fall2}) = ChangingGradient(slew_rate(spoilt) * fall_time(spoilt)[2], -slew_rate(spoilt), gradient_orientation(spoilt), fall_time(spoilt)[2], spoilt.group)
 
-rise_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1, spoilt.fall_time2 - spoilt.diff_time)
-flat_time(spoilt::SpoiltSliceSelect) = (spoilt.flat_time1, spoilt.flat_time2)
-fall_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1 - spoilt.diff_time, spoilt.fall_time2)
-duration(spoilt::SpoiltSliceSelect) = sum(rise_time(spoilt)) + sum(flat_time(spoilt)) + sum(flat_time(spoilt)) + duration(spoilt.pulse)
-slew_rate(spoilt::SpoiltSliceSelect) = spoilt.slew_rate
-inverse_slice_thickness(spoilt::SpoiltSliceSelect) = spoilt.slew_rate * spoilt.diff_time * duration(spoilt.pulse) * 1e3
-gradient_strength(spoilt::SpoiltSliceSelect) = slew_rate(spoilt) * max(spoilt.rise_time1, spoilt.fall_time2)
+@defvar begin
+    rise_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1, spoilt.fall_time2 - spoilt.diff_time)
+    flat_time(spoilt::SpoiltSliceSelect) = (spoilt.flat_time1, spoilt.flat_time2)
+    fall_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1 - spoilt.diff_time, spoilt.fall_time2)
+    duration(spoilt::SpoiltSliceSelect) = sum(rise_time(spoilt)) + sum(flat_time(spoilt)) + sum(flat_time(spoilt)) + duration(spoilt.pulse)
+    slew_rate(spoilt::SpoiltSliceSelect) = spoilt.slew_rate
+    inverse_slice_thickness(spoilt::SpoiltSliceSelect) = spoilt.slew_rate * spoilt.diff_time * duration(spoilt.pulse) * 1e3
+    gradient_strength(spoilt::SpoiltSliceSelect) = slew_rate(spoilt) * max(spoilt.rise_time1, spoilt.fall_time2)
+end
+
 get_pulse(spoilt::SpoiltSliceSelect) = spoilt.pulse
 
-function all_gradient_strengths(spoilt::SpoiltSliceSelect)
+@defvar function all_gradient_strengths(spoilt::SpoiltSliceSelect)
     grad1 = spoilt.slew_rate * rise_time(spoilt)[1]
     grad2 = grad1 - spoilt.slew_rate * flat_time(spoilt)[1]
     grad3 = spoilt.slew_rate * fall_time(spoilt)[2]
diff --git a/src/parts/trapezoids.jl b/src/parts/trapezoids.jl
index 7a6024c..0059b18 100644
--- a/src/parts/trapezoids.jl
+++ b/src/parts/trapezoids.jl
@@ -6,8 +6,7 @@ module Trapezoids
 import JuMP: @constraint
 import StaticArrays: SVector
 import LinearAlgebra: norm
-import ...Variables: qval, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, inverse_bandwidth, effective_time, duration, set_simple_constraints!, scanner_constraints!, inverse_slice_thickness
-import ...Variables: Variables, all_variables_symbols, dwell_time, inverse_fov, inverse_voxel_size, fov, voxel_size, get_gradient, get_pulse, get_readout, gradient_orientation, ramp_overlap, adjustable, adjust_internal
+import ...Variables: variables, @defvar, scanner_constraints!, get_free_variable, set_simple_constraints!, gradient_orientation, VariableType
 import ...BuildSequences: global_model
 import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent, ADC
 import ...Containers: BaseBuildingBlock
@@ -107,14 +106,16 @@ gradient_orientation(pg::Trapezoid{1}) = pg.orientation
 get_group(pg::Trapezoid) = pg.group
 get_group(pg::BaseTrapezoid) = get_group(get_gradient(pg))
 
-rise_time(pg::Trapezoid) = pg.rise_time
-flat_time(pg::Trapezoid) = pg.flat_time
-gradient_strength(g::Trapezoid) = slew_rate(g) .* rise_time(g)
-slew_rate(g::Trapezoid) = g.slew_rate
-δ(g::Trapezoid) = rise_time(g) + flat_time(g)
-duration(g::BaseTrapezoid) = 2 * rise_time(g) + flat_time(g)
+@defvar begin
+    rise_time(pg::Trapezoid) = pg.rise_time
+    flat_time(pg::Trapezoid) = pg.flat_time
+    gradient_strength(g::Trapezoid) = slew_rate(g) .* rise_time(g)
+    slew_rate(g::Trapezoid) = g.slew_rate
+    diffusion_time(g::Trapezoid) = rise_time(g) + flat_time(g)
+    duration(g::BaseTrapezoid) = 2 * rise_time(g) + flat_time(g)
 
-qval(g::BaseTrapezoid, ::Nothing, ::Nothing) = δ(g) .* gradient_strength(g) .* 2π
+    qval(g::BaseTrapezoid, ::Nothing, ::Nothing) = δ(g) .* gradient_strength(g) .* 2π
+end
 
 adjustable(::BaseTrapezoid) = :gradient
 
@@ -176,11 +177,11 @@ end
 Base.keys(::SliceSelect) = (Val(:rise), Val(:flat), Val(:pulse), Val(:fall))
 Base.getindex(pg::SliceSelect, ::Val{:pulse}) = (0., pg.pulse)
 
-inverse_slice_thickness(ss::SliceSelect) = 1e3 * gradient_strength(ss.trapezoid) .* inverse_bandwidth(ss.pulse)
+@defvar inverse_slice_thickness(ss::SliceSelect) = 1e3 * variables.gradient_strength(ss.trapezoid) .* variables.inverse_bandwidth(ss.pulse)
 
 get_pulse(ss::SliceSelect) = ss.pulse
 get_gradient(ss::SliceSelect) = ss.trapezoid
-effective_time(ss::SliceSelect) = effective_time(ss, :pulse)
+@defvar effective_time(ss::SliceSelect) = variables.effective_time(ss, :pulse)
 
 """
     LineReadout(adc; ramp_overlap=1., orientation=nothing, group=nothing, variables...)
@@ -221,10 +222,12 @@ end
 Base.keys(::LineReadout) = (Val(:rise), Val(:adc), Val(:flat), Val(:fall))
 Base.getindex(lr::LineReadout, ::Val{:adc}) = ((1 - ramp_overlap(lr)) * rise_time(lr), lr.adc)
 
-ramp_overlap(lr::LineReadout) = lr.ramp_overlap
-inverse_fov(lr::LineReadout) = 1e3 * dwell_time(lr.adc) * gradient_strength(lr.trapezoid) * lr.adc.oversample
-inverse_voxel_size(lr::LineReadout) = 1e3 * duration(lr.adc) * gradient_strength(lr.trapezoid)
-effective_time(lr::LineReadout) = effective_time(lr, :adc)
+@defvar begin
+    ramp_overlap(lr::LineReadout) = lr.ramp_overlap
+    inverse_fov(lr::LineReadout) = 1e3 * dwell_time(lr.adc) * gradient_strength(lr.trapezoid) * lr.adc.oversample
+    inverse_voxel_size(lr::LineReadout) = 1e3 * duration(lr.adc) * gradient_strength(lr.trapezoid)
+    effective_time(lr::LineReadout) = variables.effective_time(lr, :adc)
+end
 
 get_readout(lr::LineReadout) = lr.adc
 get_gradient(lr::LineReadout) = lr.trapezoid
diff --git a/src/plot.jl b/src/plot.jl
index 7dd311c..b9215fb 100644
--- a/src/plot.jl
+++ b/src/plot.jl
@@ -1,7 +1,7 @@
 module Plot
 import MakieCore: generic_plot_attributes!
 import ..Containers: BaseBuildingBlock, BaseSequence, waveform, events, start_time, ndim_grad, waveform_sequence
-import ..Variables: duration, flip_angle, phase, make_generic, gradient_orientation
+import ..Variables: make_generic, gradient_orientation, variables
 import ..Components: RFPulseComponent, ADC, InstantPulse, NoGradient, InstantGradient1D, InstantGradient3D
 
 """
@@ -16,7 +16,7 @@ struct SinglePlotLine
     event_amplitudes :: Vector{Float64}
 end
 
-duration(pl::SinglePlotLine) = iszero(length(pl.times)) ? 0. : pl.times[end]
+duration_line(pl::SinglePlotLine) = iszero(length(pl.times)) ? 0. : pl.times[end]
 SinglePlotLine(times::Vector{Float64}, amplitudes::Vector{Float64}) = SinglePlotLine(times, amplitudes, Float64[], Float64[])
 
 function SinglePlotLine(control_points::AbstractVector{<:Tuple}, duration::Number)
@@ -45,7 +45,7 @@ function SinglePlotLine(plot_lines::SinglePlotLine...)
         append!(amplitudes, pl.amplitudes)
         append!(event_times, pl.event_times .+ current_time)
         append!(event_amplitudes, pl.event_amplitudes)
-        current_time += duration(pl)
+        current_time += duration_line(pl)
     end
     return SinglePlotLine(times, amplitudes, event_times, event_amplitudes)
 end
@@ -119,7 +119,7 @@ function SequenceDiagram(bbb::BaseBuildingBlock)
     if !all([wvs isa NoGradient for (_, wvs) in waveform_sequence(bbb)])
         orientation = ndim_grad(bbb) == 3 ? 1. : gradient_orientation(bbb)
         for (index, symbol) in enumerate((:Gx, :Gy, :Gz))
-            kwargs[symbol] = SinglePlotLine([(time, (orientation .* amplitude)[index]) for (time, amplitude) in waveform(bbb)], duration(bbb))
+            kwargs[symbol] = SinglePlotLine([(time, (orientation .* amplitude)[index]) for (time, amplitude) in waveform(bbb)], variables.duration(bbb))
         end
     end
 
@@ -132,7 +132,7 @@ function SequenceDiagram(bbb::BaseBuildingBlock)
             end
             for (symbol, fn) in [(:RFx, cosd), (:RFy, sind)]
                 if event isa InstantPulse
-                    kwargs[symbol] = SinglePlotLine([0., duration(bbb)], [0., 0.], [delay], [flip_angle(event) * fn(phase(event))])
+                    kwargs[symbol] = SinglePlotLine([0., variables.duration(bbb)], [0., 0.], [delay], [variables.flip_angle(event) * fn(variables.phase(event))])
                 else
                     points = Tuple{Float64, Float64}[]
                     t_prev = p_prev = a_prev = nothing
@@ -154,34 +154,34 @@ function SequenceDiagram(bbb::BaseBuildingBlock)
                         p_prev = p
                         a_prev = a
                     end
-                    kwargs[symbol] = SinglePlotLine(points, duration(bbb))
+                    kwargs[symbol] = SinglePlotLine(points, variables.duration(bbb))
                 end
             end
         elseif event isa ADC
             if :ADC in keys(kwargs)
                 error("Cannot plot a building block with more than 1 ADC event.")
             end
-            if iszero(duration(event))
+            if iszero(variables.duration(event))
                 kwargs[:ADC] = SinglePlotLine(
-                    [0., duration(bbb)],
+                    [0., variables.duration(bbb)],
                     [0., 0.],
                     [delay], [1.]
                 )
             else
                 kwargs[:ADC] = SinglePlotLine(
-                    [0., delay, delay, delay + duration(event), delay + duration(event), duration(bbb)],
+                    [0., delay, delay, delay + variables.duration(event), delay + variables.duration(event), variables.duration(bbb)],
                     [0., 0., 1., 1., 0., 0.],
                 )
             end
         elseif event isa InstantGradient1D
-            kwargs[:G] = SinglePlotLine([0., duration(bbb)], [0., 0.], [delay], [event.qval])
+            kwargs[:G] = SinglePlotLine([0., variables.duration(bbb)], [0., 0.], [delay], [event.qval])
         elseif event isa InstantGradient3D
             for (index, symbol) in enumerate([:Gx, :Gy, :Gz])
-                kwargs[symbol] = SinglePlotLine([0., duration(bbb)], [0., 0.], [delay], [event.qval[index]])
+                kwargs[symbol] = SinglePlotLine([0., variables.duration(bbb)], [0., 0.], [delay], [event.qval[index]])
             end
         end
     end
-    return SequenceDiagram(duration(bbb); kwargs...)
+    return SequenceDiagram(variables.duration(bbb); kwargs...)
 end
 
 function SequenceDiagram(seq::BaseSequence)
diff --git a/src/printing.jl b/src/printing.jl
index 6162460..f72cfa0 100644
--- a/src/printing.jl
+++ b/src/printing.jl
@@ -1,8 +1,7 @@
 module Printing
 import JuMP: value
 import Printf: @sprintf
-import ..Variables: VariableType, variables, AbstractBlock, VariableNotAvailable, alternative_variables
-
+import ..Variables: VariableType, variables, AbstractBlock 
 
 function _robust_value(possible_number::VariableType)
     try
@@ -47,20 +46,14 @@ function Base.show(io::IO, block::AbstractBlock)
     end
 
     for fn in values(variables)
-        if fn in [fn_alt for (fn_alt, _, _, _) in values(alternative_variables)]
-            continue
-        end
         try
             numeric_value = _robust_value(fn(block))
             if isnothing(numeric_value)
                 continue
             end
             print(io, "$(nameof(fn))=$(numeric_value), ")
-        catch e
-            if e isa VariableNotAvailable
-                continue
-            end
-            rethrow()
+        catch
+            continue
         end
     end
     print(io, ")")
diff --git a/src/sequence_io/pulseq.jl b/src/sequence_io/pulseq.jl
index 6ca2a6a..035ca99 100644
--- a/src/sequence_io/pulseq.jl
+++ b/src/sequence_io/pulseq.jl
@@ -7,7 +7,7 @@ import ..PulseqIO.Types: PulseqSequence, PulseqBlock, PulseqTrapezoid, PulseqGra
 import ...Containers: Sequence, BuildingBlock, BaseBuildingBlock, events, waveform, iter_blocks
 import ...Components: GenericPulse, ADC, RFPulseComponent
 import ...Scanners: Scanner
-import ...Variables: duration, nsamples, dwell_time, make_generic
+import ...Variables: variables, make_generic
 
 function Sequence(pulseq::PulseqSequence; scanner=nothing, B0=nothing)
     if isnothing(scanner)
@@ -145,8 +145,8 @@ function PulseqBlock(block::BaseBuildingBlock; BlockDurationRaster, AdcRasterTim
                 error("Pulseq does not support a single building block containing multiple ADC events.")
             end
             adc = PulseqADC(
-                nsamples(event),
-                div(dwell_time(event), AdcRasterTime, RoundNearest),
+                variables.nsamples(event),
+                div(variables.dwell_time(event), AdcRasterTime, RoundNearest),
                 Int(div(delay, 1e-3, RoundNearest)),
                 0., 0.
             )
diff --git a/src/sequences/diffusion_spin_echoes.jl b/src/sequences/diffusion_spin_echoes.jl
index 4f8025a..bf847c9 100644
--- a/src/sequences/diffusion_spin_echoes.jl
+++ b/src/sequences/diffusion_spin_echoes.jl
@@ -2,7 +2,7 @@ module DiffusionSpinEchoes
 import ...Containers: Sequence
 import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler, refocus_pulse, dwi_gradients
 import ...Containers: start_time
-import ...Variables: get_pulse, get_readout, echo_time, duration_transverse, delay, effective_time, diffusion_time, Δ, TR, TE, repetition_time, get_gradient
+import ...Variables: get_pulse, get_readout, get_gradient, variables, @defvar
 import ...Pathways: Pathway, get_pathway
 import ...BuildSequences: build_sequence
 import ...Scanners: Default_Scanner
@@ -64,8 +64,11 @@ get_pulse(ge::DiffusionSpinEcho) = (excitation=ge[:excitation], refocus=ge[:refo
 get_gradient(ge::DiffusionSpinEcho) = (gradient=ge[:gradient], gradient2=ge[:gradient2])
 get_readout(ge::DiffusionSpinEcho) = ge.readout
 get_pathway(ge::DiffusionSpinEcho) = Pathway(ge, [90, 180], 1, group=:diffusion)
-echo_time(ge::DiffusionSpinEcho) = 2 * (effective_time(ge, :refocus) - effective_time(ge, :excitation))
-delay(ge::DiffusionSpinEcho) = duration_transverse(ge) - echo_time(ge)
-diffusion_time(ge::DiffusionSpinEcho) = start_time(ge, :gradient2) - start_time(ge, :gradient)
+
+@defvar begin
+    echo_time(ge::DiffusionSpinEcho) = 2 * (effective_time(ge, :refocus) - variables.effective_time(ge, :excitation))
+    delay(ge::DiffusionSpinEcho) = variables.duration_transverse(ge) - variables.echo_time(ge)
+    diffusion_time(ge::DiffusionSpinEcho) = start_time(ge, :gradient2) - start_time(ge, :gradient)
+end
 
 end
\ No newline at end of file
diff --git a/src/sequences/gradient_echoes.jl b/src/sequences/gradient_echoes.jl
index 703b2cd..77b1241 100644
--- a/src/sequences/gradient_echoes.jl
+++ b/src/sequences/gradient_echoes.jl
@@ -1,7 +1,7 @@
 module GradientEchoes
 import ...Containers: Sequence
 import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler
-import ...Variables: get_pulse, get_readout, echo_time, duration_transverse, TR, TE, repetition_time
+import ...Variables: get_pulse, get_readout, variables, @defvar
 import ...Pathways: Pathway, get_pathway
 import ...BuildSequences: build_sequence
 import ...Scanners: Default_Scanner
@@ -47,7 +47,7 @@ end
 get_pulse(ge::GradientEcho) = ge.excitation
 get_readout(ge::GradientEcho) = ge.readout
 get_pathway(ge::GradientEcho) = Pathway(ge, [90], 1)
-echo_time(ge::GradientEcho) = duration_transverse(ge)
+@defvar echo_time(ge::GradientEcho) = variables.duration_transverse(ge)
 
 
 
diff --git a/src/sequences/spin_echoes.jl b/src/sequences/spin_echoes.jl
index 313ab23..90ec0a4 100644
--- a/src/sequences/spin_echoes.jl
+++ b/src/sequences/spin_echoes.jl
@@ -1,7 +1,7 @@
 module SpinEchoes
 import ...Containers: Sequence
 import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler, refocus_pulse
-import ...Variables: get_pulse, get_readout, echo_time, duration_transverse, delay, effective_time, TR, TR, repetition_time
+import ...Variables: get_pulse, get_readout, variables, @defvar
 import ...Pathways: Pathway, get_pathway
 import ...BuildSequences: build_sequence
 import ...Scanners: Default_Scanner
@@ -51,8 +51,11 @@ end
 get_pulse(ge::SpinEcho) = (excitation=ge.excitation, refocus=ge.refocus)
 get_readout(ge::SpinEcho) = ge.readout
 get_pathway(ge::SpinEcho) = Pathway(ge, [90, 180], 1)
-echo_time(ge::SpinEcho) = 2 * (effective_time(ge, :refocus) - effective_time(ge, :excitation))
-delay(ge::SpinEcho) = duration_transverse(ge) - echo_time(ge)
+
+@defvar begin
+    echo_time(ge::SpinEcho) = 2 * (variables.effective_time(ge, :refocus) - variables.effective_time(ge, :excitation))
+    delay(ge::SpinEcho) = variables.duration_transverse(ge) - variables.echo_time(ge)
+end
 
 
 end
\ No newline at end of file
-- 
GitLab