diff --git a/src/MRIBuilder.jl b/src/MRIBuilder.jl
index 11be17556dfde67a8c2e9b14592c83cdddcc2470..63399d5313cbea27f0457e09ef51a522ae500682 100644
--- a/src/MRIBuilder.jl
+++ b/src/MRIBuilder.jl
@@ -3,10 +3,10 @@ Builds and optimises NMR/MRI sequences.
 """
 module MRIBuilder
 
-include("variables.jl")
-include("building_blocks.jl")
 include("scanners.jl")
 include("build_sequences.jl")
+include("variables.jl")
+include("building_blocks.jl")
 include("wait.jl")
 include("gradients/gradients.jl")
 include("pulses/pulses.jl")
diff --git a/src/build_sequences.jl b/src/build_sequences.jl
index 41deba6647f9dd6dab6cfb97cd3f2716f4a5f3b0..5600724d53a6a9426678e9f74f34e9fc30c5c957 100644
--- a/src/build_sequences.jl
+++ b/src/build_sequences.jl
@@ -2,8 +2,7 @@ module BuildSequences
 import JuMP: Model, optimizer_with_attributes, optimize!
 import Ipopt
 import Juniper
-import ..Scanners: Scanner, scanner_constraints!
-import ..BuildingBlocks: BuildingBlock, apply_simple_constraint!, match_blocks!
+import ..Scanners: Scanner
 
 const GLOBAL_MODEL = Ref(Model())
 const IGNORE_MODEL = GLOBAL_MODEL[]
@@ -75,11 +74,4 @@ function global_scanner()
 end
 
 
-scanner_constraints!(bb::BuildingBlock)  = scanner_constraints!(bb, global_scanner())
-
-apply_simple_constraint!(variable, value) = apply_simple_constraint!(global_model(), variable, value)
-match_blocks!(block1::BuildingBlock, block2::BuildingBlock, property_list) = match_blocks!(global_model(), block1, block2, property_list)
-scanner_constraints!(building_block::BuildingBlock, scanner::Scanner, func::Function) = scanner_constraints!(building_block, scanner, func)
-scanner_constraints!(building_block::BuildingBlock) = scanner_constraints!(building_block, global_scanner())
-
 end
\ No newline at end of file
diff --git a/src/building_blocks.jl b/src/building_blocks.jl
index 3c278dd276ca26e4c01e1a54a471ddf2ae8b6002..a2cab1dfb5f51c9af81fa28ec461d03536f3e2cb 100644
--- a/src/building_blocks.jl
+++ b/src/building_blocks.jl
@@ -2,6 +2,8 @@ module BuildingBlocks
 import JuMP: value, Model, @constraint, @objective, objective_function, AbstractJuMPScalar
 import Printf: @sprintf
 import ..Variables: variables, start_time, duration, end_time, gradient_strength, slew_rate, effective_time, VariableType, qval_square
+import ..BuildSequences: global_model, global_scanner
+import ..Scanners: Scanner
 
 """
 Parent type for all individual components out of which a sequence can be built.
@@ -234,17 +236,23 @@ function set_simple_constraints!(block::BuildingBlock, kwargs)
 end
 
 """
-    apply_simple_constraint!([model, ]variable, value)
+    apply_simple_constraint!(variable, value)
 
-Add a single constraint or objective to the JuMP `model`.
-This is an internal function used by [`set_simple_constraints`](@ref).
+Add a single constraint or objective to the `variable`.
+
+`value` can be one of:
+- `nothing`: do nothing
+- `:min`: minimise the variable
+- `:max`: maximise the variable
+- `number`: fix variable to this value
+- `equation`: fix variable to the result of this equation
 """
-apply_simple_constraint!(model::Model, variable, ::Nothing) = nothing
-apply_simple_constraint!(model::Model, variable, value::Symbol) = apply_simple_constraint!(model, variable, Val(value))
-apply_simple_constraint!(model::Model, variable, ::Val{:min}) = @objective model Min objective_function(model) + variable
-apply_simple_constraint!(model::Model, variable, ::Val{:max}) = @objective model Min objective_function(model) - variable
-apply_simple_constraint!(model::Model, variable, value::VariableType) = @constraint model variable == value
-apply_simple_constraint!(model::Model, variable::AbstractVector, value::AbstractVector) = [apply_simple_constraint!(model, v1, v2) for (v1, v2) in zip(variable, value)]
+apply_simple_constraint!(variable, ::Nothing) = nothing
+apply_simple_constraint!(variable, value::Symbol) = apply_simple_constraint!(variable, Val(value))
+apply_simple_constraint!(variable, ::Val{:min}) = @objective global_model() Min objective_function(global_model()) + variable
+apply_simple_constraint!(variable, ::Val{:max}) = @objective global_model() Min objective_function(global_model()) - variable
+apply_simple_constraint!(variable, value::VariableType) = @constraint model variable == value
+apply_simple_constraint!(variable::AbstractVector, value::AbstractVector) = [apply_simple_constraint!(v1, v2) for (v1, v2) in zip(variable, value)]
 
 
 """
@@ -253,9 +261,9 @@ apply_simple_constraint!(model::Model, variable::AbstractVector, value::Abstract
 Matches the listed variables between two [`BuildingBlock`](@ref) objects.
 By default all shared variables (i.e., those with the same name) are matched.
 """
-function match_blocks!(model::Model, block1::BuildingBlock, block2::BuildingBlock, property_list)
+function match_blocks!(block1::BuildingBlock, block2::BuildingBlock, property_list)
     for fn in property_list
-        @constraint model fn(block1) == fn(block2)
+        @constraint global_model() fn(block1) == fn(block2)
     end
 end
 
@@ -264,4 +272,50 @@ function match_blocks!(block1::BuildingBlock, block2::BuildingBlock)
     match_blocks!(block1, block2, property_list)
 end
 
+"""
+    scanner_constraints!(building_block[, scanner])
+
+Adds the gradient strength and slew rate constraints from a specific [`Scanner`](@ref) to a [`BuildingBlock`]{@ref}.
+
+This is applied iteratively to each part of a `Sequence`.
+"""
+scanner_constraints!(building_block::BuildingBlock) = scanner_constraints!(building_block, global_scanner())
+
+function scanner_constraints!(building_block::BuildingBlock, scanner::Scanner)
+    for func in [gradient_strength, slew_rate]
+        if isfinite(func(scanner))
+            scanner_constraints!(building_block, scanner, func)
+        end
+    end
+end
+
+function scanner_constraints!(building_block::BuildingBlock, scanner::Scanner, func::Function)
+    model = global_model()
+    if func in variables(building_block)
+        # apply constraint at this level
+        res_bb = func(building_block)
+        if res_bb isa AbstractVector
+            if isnothing(building_block.rotate)
+                # no rotation; apply constraint to each dimension independently
+                for expr in res_bb
+                    @constraint model expr <= func(scanner)
+                    @constraint model expr >= -func(scanner)
+                end
+            else
+                # with rotation: apply constraint to total squared
+                total_squared = sum(map(n->n^2, res_bb))
+                @constraint model total_squared <= func(scanner)^2
+            end
+        else
+            @constraint model res_bb <= func(scanner)
+            @constraint model res_bb >= -func(scanner)
+        end
+    elseif building_block isa ContainerBlock
+        # apply constraints at lower level
+        for (_, child_block) in get_children_blocks(building_block)
+            scanner_constraints!(child_block, scanner, func)
+        end
+    end
+end
+
 end
\ No newline at end of file
diff --git a/src/scanners.jl b/src/scanners.jl
index 6c026a8e896a8f680744637027983d1b1818d5be..b35eef4812e1e0bb89f5cb9d27871c312602ce3d 100644
--- a/src/scanners.jl
+++ b/src/scanners.jl
@@ -2,10 +2,6 @@
 Define general [`Scanner`](@ref) type and methods as well as some concrete scanners.
 """
 module Scanners
-import JuMP: Model, @constraint
-import ..Variables: gradient_strength, slew_rate
-import ..BuildingBlocks: BuildingBlock, get_children_blocks, ContainerBlock
-import ..Variables: variables
 
 const gyromagnetic_ratio = 42576.38476  # (kHz/T)
 
@@ -88,45 +84,4 @@ predefined_scanners = Dict(
     :Siemens_Connectom => Siemens_Connectom,
 )
 
-"""
-    scanner_constraints!(building_block[, scanner])
-
-Adds any constraints from a specific scanner to a [`BuildingBlock`]{@ref}.
-"""
-function scanner_constraints!(building_block::BuildingBlock, scanner::Scanner)
-    for func in [gradient_strength, slew_rate]
-        if isfinite(func(scanner))
-            scanner_constraints!(building_block, scanner, func)
-        end
-    end
-end
-
-function scanner_constraints!(model::Model, building_block::BuildingBlock, scanner::Scanner, func::Function)
-    if func in variables(building_block)
-        # apply constraint at this level
-        res_bb = func(building_block)
-        if res_bb isa AbstractVector
-            if isnothing(building_block.rotate)
-                # no rotation; apply constraint to each dimension independently
-                for expr in res_bb
-                    @constraint model expr <= func(scanner)
-                    @constraint model expr >= -func(scanner)
-                end
-            else
-                # with rotation: apply constraint to total squared
-                total_squared = sum(map(n->n^2, res_bb))
-                @constraint model total_squared <= func(scanner)^2
-            end
-        else
-            @constraint model res_bb <= func(scanner)
-            @constraint model res_bb >= -func(scanner)
-        end
-    elseif building_block isa ContainerBlock
-        # apply constraints at lower level
-        for (_, child_block) in get_children_blocks(building_block)
-            scanner_constraints!(model, child_block, scanner, func)
-        end
-    end
-end
-
 end
\ No newline at end of file
diff --git a/src/variables.jl b/src/variables.jl
index d1b7f0d9489067cc486c7cbbe4a0563656235a51..004b9a8109cccd422f794da4a174bac400a7c0a3 100644
--- a/src/variables.jl
+++ b/src/variables.jl
@@ -1,6 +1,7 @@
 module Variables
 import JuMP: @variable, Model, @objective, objective_function, value, AbstractJuMPScalar
-import ..
+import ..Scanners: gradient_strength, slew_rate
+import ..BuildSequences: global_model
 
 all_variables_symbols = [
     :block => [