From d3fb2bb6279331ef988209998a515e979031268e Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk> Date: Fri, 2 Feb 2024 17:45:30 +0000 Subject: [PATCH] Add object for single line of k-space --- src/MRIBuilder.jl | 4 +- .../gradient_pulses/trapezoid_gradients.jl | 4 +- .../gradient_readouts/gradient_readouts.jl | 6 +++ .../gradient_readouts/single_lines.jl | 38 +++++++++++++++++++ src/overlapping/overlapping.jl | 4 +- src/readouts/ADCs.jl | 7 ++-- src/variables.jl | 4 ++ 7 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 src/overlapping/gradient_readouts/gradient_readouts.jl create mode 100644 src/overlapping/gradient_readouts/single_lines.jl diff --git a/src/MRIBuilder.jl b/src/MRIBuilder.jl index 0008f1f..8523111 100644 --- a/src/MRIBuilder.jl +++ b/src/MRIBuilder.jl @@ -40,8 +40,8 @@ export InstantGradientBlock import .Readouts: InstantReadout, ADC export InstantReadout, ADC -import .Overlapping: TrapezoidGradient, SpoiltSliceSelect, interruptions, waveform -export TrapezoidGradient, SpoiltSliceSelect, interruptions, waveform +import .Overlapping: TrapezoidGradient, SpoiltSliceSelect, interruptions, waveform, SingleLine +export TrapezoidGradient, SpoiltSliceSelect, interruptions, waveform, SingleLine import .Sequences: Sequence export Sequence diff --git a/src/overlapping/gradient_pulses/trapezoid_gradients.jl b/src/overlapping/gradient_pulses/trapezoid_gradients.jl index 705eeeb..0182510 100644 --- a/src/overlapping/gradient_pulses/trapezoid_gradients.jl +++ b/src/overlapping/gradient_pulses/trapezoid_gradients.jl @@ -50,6 +50,7 @@ struct TrapezoidGradient <: AbstractOverlapping time_before_pulse :: VariableType pulse :: Union{Nothing, RFPulseBlock} time_after_pulse :: VariableType + slew_rate_1d :: Union{Nothing, VariableType} end function TrapezoidGradient(; orientation=nothing, rise_time=nothing, flat_time=nothing, rotate=nothing, scale=nothing, pulse=nothing,kwargs...) @@ -102,7 +103,8 @@ function TrapezoidGradient(; orientation=nothing, rise_time=nothing, flat_time=n scale, time_before_pulse, pulse, - time_after_pulse + time_after_pulse, + rate_1d ) set_simple_constraints!(res, kwargs) diff --git a/src/overlapping/gradient_readouts/gradient_readouts.jl b/src/overlapping/gradient_readouts/gradient_readouts.jl new file mode 100644 index 0000000..d77f58e --- /dev/null +++ b/src/overlapping/gradient_readouts/gradient_readouts.jl @@ -0,0 +1,6 @@ +module GradientReadouts + +include("single_lines.jl") + +import .SingleLines: SingleLine +end \ No newline at end of file diff --git a/src/overlapping/gradient_readouts/single_lines.jl b/src/overlapping/gradient_readouts/single_lines.jl new file mode 100644 index 0000000..736a0e4 --- /dev/null +++ b/src/overlapping/gradient_readouts/single_lines.jl @@ -0,0 +1,38 @@ +module SingleLines +import ....BuildingBlocks: set_simple_constraints! +import ....Readouts: ADC +import ....Variables: dwell_time, fov, resolution, nsamples, effective_time, gradient_strength, slew_rate, voxel_size, rise_time, duration, variables +import ...Abstract: AbstractOverlapping, waveform, interruptions +import ...GradientPulses: TrapezoidGradient + +struct SingleLine <: AbstractOverlapping + adc :: ADC + grad :: TrapezoidGradient +end + +function SingleLine(; nsamples=nothing, dwell_time=nothing, time_to_center=nothing, adc_duration=nothing, center_halfway=true, kwargs...) + readout = ADC(nsamples=nsamples, dwell_time=dwell_time, time_to_center=time_to_center, duration=adc_duration, center_halfway=center_halfway) + res = SingleLine( + readout, + TrapezoidGradient(orientation=[1, 0, 0], rotate=:FOV, flat_time=duration(readout), duration=:min) + ) + set_simple_constraints!(res, kwargs) + return res +end + +waveform(sl::SingleLine) = waveform(sl.grad) +interruptions(sl::SingleLine) = [(index=2, time=effective_time(sl.adc), object=sl.adc)] + +effective_time(sl::SingleLine) = rise_time(sl.grad) + effective_time(sl.adc) +dwell_time(sl::SingleLine) = sl.adc.dwell_time +slew_rate(sl::SingleLine) = sl.grad.slew_rate_1d +gradient_strenth(sl::SingleLine) = slew_rate(sl) * rise_time(sl.grad) +fov_inverse(sl::SingleLine) = 1e3 * dwell_time(sl) * gradient_strenth(sl) +voxel_size_inverse(sl::SingleLine) = 1e3 * duration(sl.adc) * gradient_strenth(sl) +nsamples(sl::SingleLine) = nsamples(sl.adc) +resolution(sl::SingleLine) = resolution(sl.adc) +duration(sl::SingleLine) = duration(sl.grad) + +variables(::Type{<:SingleLine}) = [dwell_time, gradient_strenth, fov_inverse, voxel_size_inverse, resolution, duration] + +end \ No newline at end of file diff --git a/src/overlapping/overlapping.jl b/src/overlapping/overlapping.jl index 3b5a7be..eda9b47 100644 --- a/src/overlapping/overlapping.jl +++ b/src/overlapping/overlapping.jl @@ -1,10 +1,12 @@ module Overlapping include("abstract.jl") include("generic.jl") -include("gradient_pulses//gradient_pulses.jl") +include("gradient_pulses/gradient_pulses.jl") +include("gradient_readouts/gradient_readouts.jl") import .Abstract: AbstractOverlapping, interruptions, waveform import .Generic: GenericOverlapping import .GradientPulses: TrapezoidGradient, SpoiltSliceSelect +import .GradientReadouts: SingleLine end \ No newline at end of file diff --git a/src/readouts/ADCs.jl b/src/readouts/ADCs.jl index 3e265d7..b8f924e 100644 --- a/src/readouts/ADCs.jl +++ b/src/readouts/ADCs.jl @@ -1,6 +1,6 @@ module ADCs import JuMP: @constraint -import ...Variables: variables, dwell_time, duration, effective_time, get_free_variable, VariableType, nsamples +import ...Variables: variables, dwell_time, duration, effective_time, get_free_variable, VariableType, nsamples, resolution import ...BuildingBlocks: BuildingBlock, apply_simple_constraint!, set_simple_constraints!, fixed import ...BuildSequences: global_model @@ -24,7 +24,7 @@ struct ADC <: BuildingBlock time_to_center :: VariableType end -function ADC(nsamples=nothing, dwell_time=nothing, time_to_center=nothing, center_halfway=true, kwargs...) +function ADC(; nsamples=nothing, dwell_time=nothing, time_to_center=nothing, center_halfway=true, kwargs...) res = ADC( get_free_variable(nsamples), get_free_variable(dwell_time), @@ -46,8 +46,9 @@ dwell_time(adc::ADC) = adc.dwell_time duration(adc::ADC) = nsamples(adc) * dwell_time(adc) time_to_center(adc::ADC) = adc.time_to_center effective_time(adc::ADC) = time_to_center(adc) +resolution(adc::ADC) = adc.nsamples -variables(::Type{<:ADC}) = [nsamples, dwell_time, duration, time_to_center] +variables(::Type{<:ADC}) = [nsamples, dwell_time, duration, time_to_center, resolution] function fixed(adc::ADC) # round nsamples during fixing diff --git a/src/variables.jl b/src/variables.jl index 7e94e0d..3c892b6 100644 --- a/src/variables.jl +++ b/src/variables.jl @@ -36,6 +36,10 @@ all_variables_symbols = [ ], :readout => [ :dwell_time => "Time between two samples in an `ADC` in ms.", + :nsamples => "Number of samples during a readout. During the optimisation this might produce non-integer values (also see [`resolution`](@ref)).", + :fov => "Size of the field of view in mm.", + :voxel_size => "Size of each voxel in mm.", + :resolution => "Number of voxels in the final readout (also see [`nsamples`](@ref)).", ] ] -- GitLab