Skip to content
Snippets Groups Projects
Verified Commit 2419cb62 authored by Michiel Cottaar's avatar Michiel Cottaar
Browse files

Fix include order

parent b8891557
No related branches found
No related tags found
No related merge requests found
...@@ -3,10 +3,10 @@ Builds and optimises NMR/MRI sequences. ...@@ -3,10 +3,10 @@ Builds and optimises NMR/MRI sequences.
""" """
module MRIBuilder module MRIBuilder
include("variables.jl")
include("building_blocks.jl")
include("scanners.jl") include("scanners.jl")
include("build_sequences.jl") include("build_sequences.jl")
include("variables.jl")
include("building_blocks.jl")
include("wait.jl") include("wait.jl")
include("gradients/gradients.jl") include("gradients/gradients.jl")
include("pulses/pulses.jl") include("pulses/pulses.jl")
......
...@@ -2,8 +2,7 @@ module BuildSequences ...@@ -2,8 +2,7 @@ module BuildSequences
import JuMP: Model, optimizer_with_attributes, optimize! import JuMP: Model, optimizer_with_attributes, optimize!
import Ipopt import Ipopt
import Juniper import Juniper
import ..Scanners: Scanner, scanner_constraints! import ..Scanners: Scanner
import ..BuildingBlocks: BuildingBlock, apply_simple_constraint!, match_blocks!
const GLOBAL_MODEL = Ref(Model()) const GLOBAL_MODEL = Ref(Model())
const IGNORE_MODEL = GLOBAL_MODEL[] const IGNORE_MODEL = GLOBAL_MODEL[]
...@@ -75,11 +74,4 @@ function global_scanner() ...@@ -75,11 +74,4 @@ function global_scanner()
end 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 end
\ No newline at end of file
...@@ -2,6 +2,8 @@ module BuildingBlocks ...@@ -2,6 +2,8 @@ module BuildingBlocks
import JuMP: value, Model, @constraint, @objective, objective_function, AbstractJuMPScalar import JuMP: value, Model, @constraint, @objective, objective_function, AbstractJuMPScalar
import Printf: @sprintf import Printf: @sprintf
import ..Variables: variables, start_time, duration, end_time, gradient_strength, slew_rate, effective_time, VariableType, qval_square 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. 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) ...@@ -234,17 +236,23 @@ function set_simple_constraints!(block::BuildingBlock, kwargs)
end end
""" """
apply_simple_constraint!([model, ]variable, value) apply_simple_constraint!(variable, value)
Add a single constraint or objective to the JuMP `model`. Add a single constraint or objective to the `variable`.
This is an internal function used by [`set_simple_constraints`](@ref).
`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!(variable, ::Nothing) = nothing
apply_simple_constraint!(model::Model, variable, value::Symbol) = apply_simple_constraint!(model, variable, Val(value)) apply_simple_constraint!(variable, value::Symbol) = apply_simple_constraint!(variable, Val(value))
apply_simple_constraint!(model::Model, variable, ::Val{:min}) = @objective model Min objective_function(model) + variable apply_simple_constraint!(variable, ::Val{:min}) = @objective global_model() Min objective_function(global_model()) + variable
apply_simple_constraint!(model::Model, variable, ::Val{:max}) = @objective model Min objective_function(model) - variable apply_simple_constraint!(variable, ::Val{:max}) = @objective global_model() Min objective_function(global_model()) - variable
apply_simple_constraint!(model::Model, variable, value::VariableType) = @constraint model variable == value apply_simple_constraint!(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::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 ...@@ -253,9 +261,9 @@ apply_simple_constraint!(model::Model, variable::AbstractVector, value::Abstract
Matches the listed variables between two [`BuildingBlock`](@ref) objects. Matches the listed variables between two [`BuildingBlock`](@ref) objects.
By default all shared variables (i.e., those with the same name) are matched. 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 for fn in property_list
@constraint model fn(block1) == fn(block2) @constraint global_model() fn(block1) == fn(block2)
end end
end end
...@@ -264,4 +272,50 @@ function match_blocks!(block1::BuildingBlock, block2::BuildingBlock) ...@@ -264,4 +272,50 @@ function match_blocks!(block1::BuildingBlock, block2::BuildingBlock)
match_blocks!(block1, block2, property_list) match_blocks!(block1, block2, property_list)
end 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 end
\ No newline at end of file
...@@ -2,10 +2,6 @@ ...@@ -2,10 +2,6 @@
Define general [`Scanner`](@ref) type and methods as well as some concrete scanners. Define general [`Scanner`](@ref) type and methods as well as some concrete scanners.
""" """
module 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) const gyromagnetic_ratio = 42576.38476 # (kHz/T)
...@@ -88,45 +84,4 @@ predefined_scanners = Dict( ...@@ -88,45 +84,4 @@ predefined_scanners = Dict(
:Siemens_Connectom => Siemens_Connectom, :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 end
\ No newline at end of file
module Variables module Variables
import JuMP: @variable, Model, @objective, objective_function, value, AbstractJuMPScalar import JuMP: @variable, Model, @objective, objective_function, value, AbstractJuMPScalar
import .. import ..Scanners: gradient_strength, slew_rate
import ..BuildSequences: global_model
all_variables_symbols = [ all_variables_symbols = [
:block => [ :block => [
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment