diff --git a/src/MRIBuilder.jl b/src/MRIBuilder.jl index 5f75a246ffedbd1d4908398df9586be6ef501181..09a90fccd93b5dad93c62094b69648786c6a56e7 100644 --- a/src/MRIBuilder.jl +++ b/src/MRIBuilder.jl @@ -32,8 +32,8 @@ export ConcreteBlocks, AbstractConcreteBlock import .Wait: WaitBlock export WaitBlock -import .Containers: Sequence, FixedBlock -export Sequence, FixedBlock +import .Containers: Sequence, FixedBlock, FixedSequence +export Sequence, FixedBlock, FixedSequence import .Gradients: PulsedGradient, InstantGradientBlock, FixedGradient export PulsedGradient, InstantGradientBlock, FixedGradient diff --git a/src/building_blocks.jl b/src/building_blocks.jl index a28ba2b6a4bd5c2aea25c8cffd0df55c3095f70e..ba927b0da94f5205cd2e84cbd539fa97e3e04088 100644 --- a/src/building_blocks.jl +++ b/src/building_blocks.jl @@ -9,7 +9,7 @@ Parent type for all individual components out of which a sequence can be built. Required methods: - [`duration`](@ref)(block, parameters): Return block duration in ms. -- [`fixed`](block): Return an equivalent fixed BuildingBlock (i.e., `FixedBlock`, `FixedPulse`, `FixedGradient`, `FixedInstantPulse`, `FixedInstantGradient`, or `InstantReadout`). These all have in common that they have no free variables and explicitly set any gradient and RF pulse profiles. +- [`fixed`](block): Return the equivalent fixed BuildingBlock (i.e., `FixedBlock`, `FixedPulse`, `FixedGradient`, `FixedInstantPulse`, `FixedInstantGradient`, or `InstantReadout`). These all have in common that they have no free variables and explicitly set any gradient and RF pulse profiles. - [`variables`](@ref): A list of all functions that are used to compute variables of the building block. Any of these can be used in constraints or objective functions. """ abstract type BuildingBlock end @@ -71,9 +71,9 @@ to_block(bb::BuildingBlock) = bb """ fixed(block::BuildingBlock) -Return an equivalent fixed BuildingBlock. +Return the fixed equivalent of the `BuildingBlock` -Possible return types are `FixedBlock`, `FixedPulse`, `FixedGradient`, `FixedInstantPulse`, `FixedInstantGradient`, or `InstantReadout`. +Possible return types are `FixedSequence`, `FixedBlock`, `FixedPulse`, `FixedGradient`, `FixedInstantPulse`, `FixedInstantGradient`, or `InstantReadout`. These all have in common that they have no free variables and explicitly set any gradient and RF pulse profiles. """ function fixed end diff --git a/src/containers/containers.jl b/src/containers/containers.jl index 28e1a9e1b724eafa52b56328f91e02a7c175c7dc..9ef11dd3393ef41abc3f5e9fc4222bfa891d73b4 100644 --- a/src/containers/containers.jl +++ b/src/containers/containers.jl @@ -11,5 +11,5 @@ include("sequences.jl") import ..BuildingBlocks: ContainerBlock, get_children_blocks import ..FixedBlocks: FixedBlock -import .Sequences: Sequence +import .Sequences: Sequence, FixedSequence end \ No newline at end of file diff --git a/src/containers/fixed_blocks.jl b/src/containers/fixed_blocks.jl index 086f725e7e24d6b205e780f774a64c29ee302348..6443f63101a34097bacf0fc5b6095d8f398677a3 100644 --- a/src/containers/fixed_blocks.jl +++ b/src/containers/fixed_blocks.jl @@ -5,6 +5,7 @@ import ...BuildingBlocks: ContainerBlock import ...Gradients: FixedGradient import ...Pulses: FixedPulse import ...Variables: duration, variables +import ...WaitBlocks: WaitBlock """ FixedBlock(duration=nothing; pulse_delay=0., pulse=nothing, gradient_delay=0., gradient=nothing, readout_times=[]) @@ -47,6 +48,7 @@ duration(fb::FixedBlock) = fb.duration variables(::Type{<:FixedBlock}) = [] +fixed(wb::WaitBlock) = FixedBlock(value(duration(wb))) end \ No newline at end of file diff --git a/src/containers/sequences.jl b/src/containers/sequences.jl index 0422e06618b440b8ac6b1f74cd6336f9e141ca01..6692d51ab75e9c711f652d26750e87fbe1604d45 100644 --- a/src/containers/sequences.jl +++ b/src/containers/sequences.jl @@ -5,7 +5,10 @@ module Sequences import JuMP: Model, @constraint import ...BuildSequences: @global_model_constructor import ...Variables: variables, start_time, duration, VariableType, get_free_variable, TR -import ...BuildingBlocks: BuildingBlock, ContainerBlock, to_block, get_children_blocks, scanner_constraints! +import ...BuildingBlocks: BuildingBlock, ContainerBlock, to_block, get_children_blocks, scanner_constraints!, fixed +import ..FixedBlocks: FixedBlock + +abstract type AbstractSequence <: ContainerBlock end """ Sequence(building_blocks...; TR=nothing, scanner=nothing) @@ -21,7 +24,7 @@ or be embedded as a [`BuildingBlock`](@ref) into higher-order `Sequence` or othe ## Variables - [`TR`](@ref): repetition time of sequence in ms. """ -struct Sequence <: ContainerBlock +struct Sequence <: AbstractSequence model :: Model blocks :: Vector{<:BuildingBlock} TR :: VariableType @@ -43,9 +46,9 @@ end Sequence(model::Model, blocks...; TR=nothing, scanner=nothing) = Sequence(model, [blocks...]; TR=TR, scanner=scanner) -Base.length(seq::Sequence) = length(seq.blocks) -Base.getindex(seq::Sequence, index) = seq.blocks[index] -get_children_blocks(seq::Sequence) = enumerate(seq.blocks) +Base.length(seq::AbstractSequence) = length(seq.blocks) +Base.getindex(seq::AbstractSequence, index) = seq.blocks[index] +get_children_blocks(seq::AbstractSequence) = enumerate(seq.blocks) """ start_time(sequence::Sequence, index::Integer, args...) @@ -54,9 +57,9 @@ Returns the starting time of the [`BuildingBlock`](@ref) with index `index`. Additional `args` can be used to select a sub-block of that [`BuildingBlock`](@ref). The starting time is returned with respect to the start of this sequence. """ -start_time(seq::Sequence) = 0. -start_time(seq::Sequence, index::Integer) = iszero(index) ? start_time(seq) : (start_time(seq, index-1) + duration(seq[index])) -start_time(seq::Sequence, index::Integer, args...) = start_time(seq, index) + start_time(seq[index], args...) +start_time(seq::AbstractSequence) = 0. +start_time(seq::AbstractSequence, index::Integer) = iszero(index) ? start_time(seq) : (start_time(seq, index-1) + duration(seq[index])) +start_time(seq::AbstractSequence, index::Integer, args...) = start_time(seq, index) + start_time(seq[index], args...) """ end_time(sequence::Sequence, index::Integer, args...) @@ -65,15 +68,29 @@ Returns the end time of the [`BuildingBlock`](@ref) with index `index`. Additional `args` can be used to select a sub-block of that [`BuildingBlock`](@ref). The end time is returned with respect to the start of this sequence. """ -end_time(seq::Sequence, index::Integer) = start_time(seq, index) + duration(seq[index]) -end_time(seq::Sequence, index::Integer, args...) = start_time(seq, index) + end_time(seq[index], args...) +end_time(seq::AbstractSequence, index::Integer) = start_time(seq, index) + duration(seq[index]) +end_time(seq::AbstractSequence, index::Integer, args...) = start_time(seq, index) + end_time(seq[index], args...) -duration(seq::Sequence) = end_time(seq, length(seq)) +duration(seq::AbstractSequence) = end_time(seq, length(seq)) -TR(seq::Sequence) = seq.TR +TR(seq::AbstractSequence) = seq.TR variables(::Type{<:Sequence}) = [TR] +struct FixedSequence <: AbstractSequence + blocks :: Vector{<:BuildingBlock} + TR :: Number +end + +function fixed(seq::Sequence) + FixedSequence( + fixed.(seq.blocks), + value(TR(seq)) + ) +end + +variables(::Type{<:FixedSequence}) = [] + end