diff --git a/src/all_building_blocks/spoilt_slice_selects.jl b/src/all_building_blocks/spoilt_slice_selects.jl
index 2210b0ad09b969c22f2bb0e7d4eb08febe972492..2c40aa0ae7ef6b8bdd9d10c2066b81da7dc85875 100644
--- a/src/all_building_blocks/spoilt_slice_selects.jl
+++ b/src/all_building_blocks/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, qvec, gradient_strength, slew_rate, inverse_slice_thickness, get_free_variable
+import ...Variables: VariableType, duration, rise_time, flat_time, effective_time, qvec, gradient_strength, slew_rate, inverse_slice_thickness, get_free_variable, get_pulse
 import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent
 import ..BaseBuildingBlocks: BaseBuildingBlock
 
@@ -92,6 +92,7 @@ duration(spoilt::SpoiltSliceSelect) = sum(rise_time(spoilt)) + sum(flat_time(spo
 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)
+get_pulse(spoilt::SpoiltSliceSelect) = spoilt.pulse
 function all_gradient_strengths(spoilt::SpoiltSliceSelect)
     grad1 = spoilt.slew_rate * rise_time(spoilt)[1]
     grad2 = grad1 - spoilt.slew_rate * flat_time(spoilt)[1]
diff --git a/src/all_building_blocks/trapezoids.jl b/src/all_building_blocks/trapezoids.jl
index 21a1dff2330b69c46c6c635cce9ecc30947e4885..58d6aeacd97e6aa900d23cbbbaf1ac6f72178f31 100644
--- a/src/all_building_blocks/trapezoids.jl
+++ b/src/all_building_blocks/trapezoids.jl
@@ -7,7 +7,7 @@ import JuMP: @constraint
 import StaticArrays: SVector
 import LinearAlgebra: norm
 import ...Variables: qvec, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, inverse_bandwidth, effective_time, qval_square, 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
+import ...Variables: Variables, all_variables_symbols, dwell_time, inverse_fov, inverse_voxel_size, fov, voxel_size, get_gradient, get_pulse, get_readout
 import ...BuildSequences: global_model
 import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent, ADC
 import ..BaseBuildingBlocks: BaseBuildingBlock
@@ -108,10 +108,6 @@ slew_rate(g::Trapezoid) = g.slew_rate
 δ(g::Trapezoid) = rise_time(g) + flat_time(g)
 duration(g::Trapezoid) = 2 * rise_time(g) + flat_time(g)
 
-for func in (:rise_time, :flat_time, :gradient_strength, :slew_rate, :δ, :duration, :qvec)
-    @eval $func(bt::BaseTrapezoid) = $func(bt.trapezoid)
-end
-
 qvec(g::BaseTrapezoid, ::Nothing, ::Nothing) = δ(g) .* gradient_strength(g) .* 2π
 
 """
@@ -146,12 +142,8 @@ Base.getindex(pg::SliceSelect, ::Val{:pulse}) = pg.pulse
 
 inverse_slice_thickness(ss::SliceSelect) = 1e3 * gradient_strength(ss.trapezoid) .* inverse_bandwidth(ss.pulse)
 
-for func in all_variables_symbols[:pulse]
-    if func in (:inverse_slice_thickness, :slice_thickness)
-        continue
-    end
-    Variables.$func(ss::SliceSelect) = Variables.$func(ss.pulse)
-end
+get_pulse(ss::SliceSelect) = ss.pulse
+get_gradient(ss::SliceSelect) = ss.trapezoid
 
 """
     LineReadout(adc; ramp_overlap=1., orientation=nothing, group=nothing, variables...)
@@ -188,11 +180,7 @@ ramp_overlap(lr::LineReadout) = lr.ramp_overlap
 inverse_fov(lr::LineReadout) = @. 1e3 * dwell_time(lr.adc) * gradient_strength(lr.trapezoid)
 inverse_voxel_size(lr::LineReadout) = @. 1e3 * duration(lr.adc) * gradient_strength(lr.trapezoid)
 
-for func in all_variables_symbols[:readout]
-    if func in (:inverse_fov, :slice_fov, :inverse_voxel_size, :slice_voxel_size, :ramp_overlap)
-        continue
-    end
-    Variables.$func(lr::LineReadout) = Variables.$func(lr.adc)
-end
+get_readout(lr::LineReadout) = rl.adc
+get_gradient(lr::LineReadout) = rl.trapezoid
 
 end
\ No newline at end of file
diff --git a/src/variables.jl b/src/variables.jl
index 1101fd02bbea9f70a887db5854dd368937f31ff2..7ce17ff4d5feb8ce44b607c4d21ab7b99ed2d769 100644
--- a/src/variables.jl
+++ b/src/variables.jl
@@ -8,6 +8,7 @@ In addition this defines:
 - [`VariableNotAvailable`](@ref): error raised if variable is not defined for specific [`AbstractBlock`](@ref).
 - [`set_simple_constraints`](@ref): call [`apply_simple_constraint`](@ref) for each keyword argument.
 - [`apply_simple_constraint`](@ref): set a simple equality constraint.
+- [`get_pulse`](@ref)/[`get_gradient`](@ref)/[`get_readout`](@ref): Used to get the pulse/gradient/readout part of a building block
 """
 module Variables
 import JuMP: @variable, Model, @objective, objective_function, value, AbstractJuMPScalar
@@ -133,6 +134,33 @@ function get_free_variable(::Val{:max})
     return var
 end
 
+"""
+    get_pulse(building_block)]
+
+Get the pulse played out during the building block.
+
+Any `pulse` variables not explicitly defined for this building block will be passed on to the pulse.
+"""
+function get_pulse end
+
+"""
+    get_gradient(building_block)]
+
+Get the gradient played out during the building block.
+
+Any `gradient` variables not explicitly defined for this building block will be passed on to the gradient.
+"""
+function get_gradient end
+
+"""
+    get_readout(building_block)]
+
+Get the readout played out during the building block.
+
+Any `readout` variables not explicitly defined for this building block will be passed on to the readout.
+"""
+function get_gradient end
+
 """
     bmat_gradient(gradient::GradientBlock, qstart=(0, 0, 0))
 
@@ -165,29 +193,38 @@ function Base.showerror(io::IO, e::VariableNotAvailable)
 end
 
 
-for variable_func in keys(variables)
-    if variable_func in [:qval_square, :qval]
-        continue
-    end
-    @eval function Variables.$variable_func(bb::BuildingBlock)
-        if Variables.$variable_func in keys(alternative_variables)
-            alt_var, forward, backward, _ = alternative_variables[Variables.$variable_func]
+for (target_name, all_vars) in pairs(all_variables_symbols)
+    for variable_func in keys(all_vars)
+        if variable_func in [:qval_square, :qval]
+            continue
+        end
+        @eval function Variables.$variable_func(bb::BuildingBlock)
             try
-                value = alt_var(bb)
-                if value isa Number
-                    return backward(value)
-                elseif value isa AbstractArray{<:Number}
-                    return backward.(value)
+                if Variables.$variable_func in keys(alternative_variables)
+                    alt_var, forward, backward, _ = alternative_variables[Variables.$variable_func]
+                    try
+                        value = alt_var(bb)
+                        if value isa Number
+                            return backward(value)
+                        elseif value isa AbstractArray{<:Number}
+                            return backward.(value)
+                        end
+                    catch e
+                        if e isa VariableNotAvailable
+                            throw(VariableNotAvailable(typeof(bb), Variables.$variable_func))
+                        end
+                        rethrow()
+                    end
+                    throw(VariableNotAvailable(typeof(bb), Variables.$variable_func, alt_var))
                 end
+                throw(VariableNotAvailable(typeof(bb), Variables.$variable_func))
             catch e
-                if e isa VariableNotAvailable
-                    throw(VariableNotAvailable(typeof(bb), Variables.$variable_func))
+                if e isa VariableNotAvailable && hasmethod(get_$(target_name), Tuple(typeof(bb))) && $(target_name) in (:pulse, :readout)
+                    return Variables.$variable_func(get_$(target_name)(bb))
                 end
                 rethrow()
             end
-            throw(VariableNotAvailable(typeof(bb), Variables.$variable_func, alt_var))
         end
-        throw(VariableNotAvailable(typeof(bb), Variables.$variable_func))
     end
 end