From 197d83dd5e5b5cd01bd9bd1c2aa229964b64d2f1 Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk> Date: Mon, 26 Feb 2024 16:04:50 +0000 Subject: [PATCH] Compute edge and start time --- src/MRIBuilder.jl | 4 +-- src/components/readouts/ADCs.jl | 1 + src/components/readouts/readouts.jl | 2 +- src/components/readouts/single_readouts.jl | 3 ++- src/containers/abstract.jl | 21 +++++++++++++++ src/containers/base_sequences.jl | 20 +++++++++++++- src/containers/building_blocks.jl | 31 ++++++++++++++++++---- src/containers/containers.jl | 2 +- 8 files changed, 73 insertions(+), 11 deletions(-) diff --git a/src/MRIBuilder.jl b/src/MRIBuilder.jl index 59326aa..2905d98 100644 --- a/src/MRIBuilder.jl +++ b/src/MRIBuilder.jl @@ -26,8 +26,8 @@ export variables, duration, effective_time, flip_angle, amplitude, phase, freque import .Components: InstantPulse, ConstantPulse, SincPulse, GenericPulse, InstantGradient, SingleReadout, ADC export InstantPulse, ConstantPulse, SincPulse, GenericPulse, InstantGradient, SingleReadout, ADC -import .Containers: ContainerBlock, start_time, end_time, waveform, waveform_sequence, events, BaseBuildingBlock, BuildingBlock, Wait, BaseSequence, nrepeat, Sequence, AlternativeBlocks, match_blocks!, get_index_single_TR -export ContainerBlock, start_time, end_time, waveform, waveform_sequence, events, BaseBuildingBlock, BuildingBlock, Wait, BaseSequence, nrepeat, Sequence, AlternativeBlocks, match_blocks!, get_index_single_TR +import .Containers: ContainerBlock, start_time, end_time, waveform, waveform_sequence, events, BaseBuildingBlock, BuildingBlock, Wait, BaseSequence, nrepeat, Sequence, AlternativeBlocks, match_blocks!, get_index_single_TR, readout_times, edge_times +export ContainerBlock, start_time, end_time, waveform, waveform_sequence, events, BaseBuildingBlock, BuildingBlock, Wait, BaseSequence, nrepeat, Sequence, AlternativeBlocks, match_blocks!, get_index_single_TR, readout_times, edge_times import .Pathways: Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway export Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway diff --git a/src/components/readouts/ADCs.jl b/src/components/readouts/ADCs.jl index b4a6b7e..ca5792f 100644 --- a/src/components/readouts/ADCs.jl +++ b/src/components/readouts/ADCs.jl @@ -48,6 +48,7 @@ function ADC(; resolution=nothing, dwell_time=nothing, time_to_center=nothing, c return res end +readout_times(adc::ADC) = range(0, duration(adc), Int(nsamples(adc))) oversample(adc::ADC) = adc.oversample nsamples(adc::ADC) = resolution(adc) * oversample(adc) dwell_time(adc::ADC) = adc.dwell_time diff --git a/src/components/readouts/readouts.jl b/src/components/readouts/readouts.jl index b28a9cd..0b6ec5d 100644 --- a/src/components/readouts/readouts.jl +++ b/src/components/readouts/readouts.jl @@ -3,6 +3,6 @@ include("ADCs.jl") include("single_readouts.jl") import ..AbstractTypes: ReadoutComponent -import .ADCs: ADC +import .ADCs: ADC, readout_times import .SingleReadouts: SingleReadout end \ No newline at end of file diff --git a/src/components/readouts/single_readouts.jl b/src/components/readouts/single_readouts.jl index c814763..dfaf8fc 100644 --- a/src/components/readouts/single_readouts.jl +++ b/src/components/readouts/single_readouts.jl @@ -2,7 +2,7 @@ module SingleReadouts import JuMP: @constraint import ...AbstractTypes: ReadoutComponent import ....Variables: duration, effective_time, make_generic -import ..ADCs: ADC +import ..ADCs: ADC, readout_times """ SingleReadout() @@ -28,6 +28,7 @@ end duration(::SingleReadout) = 0. effective_time(::SingleReadout) = 0. +readout_times(::SingleReadout) = [0.] make_generic(::SingleReadout) = ADC(1, 0., 0., 0.) end \ No newline at end of file diff --git a/src/containers/abstract.jl b/src/containers/abstract.jl index 669ff1b..8cb582a 100644 --- a/src/containers/abstract.jl +++ b/src/containers/abstract.jl @@ -1,5 +1,6 @@ module Abstract import ...Variables: AbstractBlock, duration, effective_time +import ...Components.Readouts: readout_times """ Parent type for `BuildingBlock` or `BaseSequence`, i.e., any building block that contains other MRI components/blocks. @@ -43,5 +44,25 @@ Also see [`duration`](@ref), [`start_time`](@ref), and [`end_time`](@ref) effective_time(container::ContainerBlock, index, indices...) = start_time(container, index) + effective_time(container[index], indices...) +""" + readout_times(sequence/ADC) + +Return the times of all of the readout events in ms. +""" +function readout_times end + +""" + edge_times(container) + +Returns all the edge times during a sequence in ms. + +Edges are defined as any time, when: +- the edge of a building block +- the slope of the gradient profile changes suddenly +- an RF pulse starts or ends +""" +function edge_times end + + end \ No newline at end of file diff --git a/src/containers/base_sequences.jl b/src/containers/base_sequences.jl index 0302288..281580d 100644 --- a/src/containers/base_sequences.jl +++ b/src/containers/base_sequences.jl @@ -7,7 +7,7 @@ import JuMP: @constraint import ...Variables: get_free_variable, repetition_time, VariableType, duration, variables, VariableNotAvailable, Variables, set_simple_constraints!, TR, make_generic import ...BuildSequences: global_model import ...Components: EventComponent -import ..Abstract: ContainerBlock, start_time +import ..Abstract: ContainerBlock, start_time, readout_times, edge_times import ..BuildingBlocks: Wait, BuildingBlock, BaseBuildingBlock """ @@ -83,6 +83,22 @@ repetition_time(bs::BaseSequence) = duration(bs) duration(bs::BaseSequence{0}) = 0. duration(bs::BaseSequence) = sum(duration.(bs); init=0.) +function readout_times(seq::BaseSequence) + res = Float64[] + for (index, block) in enumerate(seq) + append!(res, readout_times(block) .+ start_time(seq, index)) + end + return res +end + +function edge_times(seq::BaseSequence) + res = Float64[] + for (index, block) in enumerate(seq) + append!(res, edge_times(block) .+ start_time(seq, index)) + end + return unique(res) +end + """ Sequence(blocks; name=:Sequence, variables...) Sequence(blocks...; name=:Sequence, variables...) @@ -153,4 +169,6 @@ function make_generic(seq::BaseSequence) return Sequence(blocks) end + + end diff --git a/src/containers/building_blocks.jl b/src/containers/building_blocks.jl index 2856f2f..7fe8d03 100644 --- a/src/containers/building_blocks.jl +++ b/src/containers/building_blocks.jl @@ -5,9 +5,9 @@ module BuildingBlocks import LinearAlgebra: norm import JuMP: @constraint import StaticArrays: SVector -import ..Abstract: ContainerBlock, start_time +import ..Abstract: ContainerBlock, start_time, readout_times, edge_times, end_time import ...BuildSequences: global_model -import ...Components: BaseComponent, GradientWaveform, EventComponent, NoGradient, ChangingGradient, ConstantGradient, split_gradient, DelayedEvent, RFPulseComponent, ReadoutComponent +import ...Components: BaseComponent, GradientWaveform, EventComponent, NoGradient, ChangingGradient, ConstantGradient, split_gradient, DelayedEvent, RFPulseComponent, ReadoutComponent, InstantGradient import ...Variables: qval, bmat_gradient, effective_time, get_free_variable, qval3, slew_rate, gradient_strength import ...Variables: VariableType, duration, make_generic, get_pulse, get_readout, scanner_constraints! @@ -112,14 +112,12 @@ equal_key(i1, i2) = i1 == i2 function start_time(building_block::BaseBuildingBlock, index) time = 0. - prev_time = 0. for key in keys(building_block) if equal_key(key, index) - return prev_time + return time end component = building_block[key] if component isa GradientWaveform - prev_time = time time += duration(component) end end @@ -206,6 +204,29 @@ function bmat_gradient(bb::BaseBuildingBlock, qstart, index1, index2) end bmat_gradient(bb::BaseBuildingBlock, qstart) = bmat_gradient(bb, qstart, nothing, nothing) +function readout_times(bb::BaseBuildingBlock) + res = Float64[] + for (key, event) in events(bb) + if event isa ReadoutComponent + append!(res, readout_times(event) .+ start_time(bb, key)) + end + end + return res +end + +function edge_times(bb::BaseBuildingBlock) + res = Float64[] + for key in keys(bb) + object = bb[key] + if object isa Union{GradientWaveform, RFPulseComponent, InstantGradient} + @show key start_time(bb, key) end_time(bb, key) + push!(res, start_time(bb, key)) + push!(res, end_time(bb, key)) + end + end + return sort(unique(res)) +end + """ BuildingBlock(waveform, events; duration=nothing, orientation=nothing, group) diff --git a/src/containers/containers.jl b/src/containers/containers.jl index f2df3a1..4bd983b 100644 --- a/src/containers/containers.jl +++ b/src/containers/containers.jl @@ -4,7 +4,7 @@ include("building_blocks.jl") include("base_sequences.jl") include("alternatives.jl") -import .Abstract: ContainerBlock, start_time, end_time, effective_time +import .Abstract: ContainerBlock, start_time, end_time, effective_time, readout_times, edge_times import .BuildingBlocks: BaseBuildingBlock, BuildingBlock, Wait, waveform, waveform_sequence, events, ndim_grad import .BaseSequences: BaseSequence, Sequence, nrepeat, get_index_single_TR import .Alternatives: AlternativeBlocks, match_blocks! -- GitLab