Skip to content
Snippets Groups Projects
Unverified Commit 9c8404a0 authored by Michiel Cottaar's avatar Michiel Cottaar
Browse files

Update code to use @defvar

parent 44a2dffe
No related branches found
No related tags found
1 merge request!2Define variables through new @defvar macro
This commit is part of merge request !2. Comments created here will be created in the context of that merge request.
...@@ -9,12 +9,12 @@ include("variables.jl") ...@@ -9,12 +9,12 @@ include("variables.jl")
include("components/components.jl") include("components/components.jl")
include("containers/containers.jl") include("containers/containers.jl")
include("pathways.jl") include("pathways.jl")
#include("parts/parts.jl") include("parts/parts.jl")
#include("post_hoc.jl") include("post_hoc.jl")
#include("sequences/sequences.jl") include("sequences/sequences.jl")
#include("printing.jl") include("printing.jl")
#include("sequence_io/sequence_io.jl") include("sequence_io/sequence_io.jl")
#include("plot.jl") include("plot.jl")
import .BuildSequences: build_sequence, global_model, global_scanner, fixed import .BuildSequences: build_sequence, global_model, global_scanner, fixed
export build_sequence, global_model, global_scanner, fixed export build_sequence, global_model, global_scanner, fixed
...@@ -34,22 +34,22 @@ export ContainerBlock, start_time, end_time, waveform, waveform_sequence, events ...@@ -34,22 +34,22 @@ export ContainerBlock, start_time, end_time, waveform, waveform_sequence, events
import .Pathways: Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway import .Pathways: Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway
export Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway export Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway
#import .Parts: dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size import .Parts: dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size
#export dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size export dwi_gradients, readout_event, excitation_pulse, refocus_pulse, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout, interpret_image_size
#import .PostHoc: adjust, merge_sequences import .PostHoc: adjust, merge_sequences
#export adjust, merge_sequences export adjust, merge_sequences
#import .Sequences: GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI import .Sequences: GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI
#export GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI export GradientEcho, SpinEcho, DiffusionSpinEcho, DW_SE, DWI
#import .SequenceIO: read_sequence, write_sequence import .SequenceIO: read_sequence, write_sequence
#export read_sequence, write_sequence export read_sequence, write_sequence
#import .Plot: plot_sequence import .Plot: plot_sequence
#export plot_sequence export plot_sequence
#import JuMP: @constraint, @objective, objective_function, value, Model import JuMP: @constraint, @objective, objective_function, value, Model
#export @constraint, @objective, objective_function, value, Model export @constraint, @objective, objective_function, value, Model
end end
...@@ -2,7 +2,7 @@ module EPIReadouts ...@@ -2,7 +2,7 @@ module EPIReadouts
import ...Containers: BaseSequence, get_index_single_TR import ...Containers: BaseSequence, get_index_single_TR
import ..Trapezoids: Trapezoid, opposite_kspace_lines, LineReadout import ..Trapezoids: Trapezoid, opposite_kspace_lines, LineReadout
import ...Components: ADC import ...Components: ADC
import ...Variables: get_free_variable, VariableType, qval, qval3, set_simple_constraints!, resolution, inverse_voxel_size, inverse_fov, resolution, get_readout, apply_simple_constraint!, effective_time, voxel_size, ramp_overlap, oversample, dwell_time import ...Variables: get_free_variable, VariableType, set_simple_constraints!, get_readout, apply_simple_constraint!, variables, @defvar
import ...Pathways: PathwayWalker, update_walker_till_time!, walk_pathway! import ...Pathways: PathwayWalker, update_walker_till_time!, walk_pathway!
""" """
...@@ -49,10 +49,10 @@ function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, gro ...@@ -49,10 +49,10 @@ function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, gro
get_free_variable(nothing), get_free_variable(nothing),
ky_lines ky_lines
) )
apply_simple_constraint!(qval3(res.start_gradient), VariableType[-qval(pos)/2, ky_lines[1] * res.ky_step, 0.]) apply_simple_constraint!(variables.qval3(res.start_gradient), VariableType[-variables.qval(pos)/2, ky_lines[1] * res.ky_step, 0.])
if recenter if recenter
sign = isodd(length(ky_lines)) ? -1 : 1 sign = isodd(length(ky_lines)) ? -1 : 1
apply_simple_constraint!(qval3(res.recenter_gradient), VariableType[sign * qval(pos)/2, -ky_lines[end] * res.ky_step, 0.]) apply_simple_constraint!(variables.qval3(res.recenter_gradient), VariableType[sign * variables.qval(pos)/2, -ky_lines[end] * res.ky_step, 0.])
end end
for shift in unique(ky_lines[2:end] - ky_lines[1:end-1]) for shift in unique(ky_lines[2:end] - ky_lines[1:end-1])
res.blips[shift] = Trapezoid(orientation=[0, shift > 0 ? 1 : -1, 0], group=group, qval=abs(shift) * res.ky_step) res.blips[shift] = Trapezoid(orientation=[0, shift > 0 ? 1 : -1, 0], group=group, qval=abs(shift) * res.ky_step)
...@@ -61,16 +61,18 @@ function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, gro ...@@ -61,16 +61,18 @@ function EPIReadout(; resolution::AbstractVector{<:Integer}, recenter=false, gro
return res return res
end end
inverse_fov(epi::EPIReadout) = [inverse_fov(epi.positive_line), 1e3 * epi.ky_step] @defvar begin
inverse_voxel_size(epi::EPIReadout) = [inverse_voxel_size(epi.positive_line), 1e3 * epi.ky_step * maximum(abs.(epi.ky_lines))] inverse_fov(epi::EPIReadout) = [variables.inverse_fov(epi.positive_line), 1e3 * epi.ky_step]
resolution(epi::EPIReadout) = [resolution(epi.positive_line), maximum(abs.(epi.ky_lines))] inverse_voxel_size(epi::EPIReadout) = [variables.inverse_voxel_size(epi.positive_line), 1e3 * epi.ky_step * maximum(abs.(epi.ky_lines))]
resolution(epi::EPIReadout) = [variables.resolution(epi.positive_line), maximum(abs.(epi.ky_lines))]
end
get_readout(epi::EPIReadout) = epi.positive_line get_readout(epi::EPIReadout) = epi.positive_line
function effective_time(epi::EPIReadout) @defvar function effective_time(epi::EPIReadout)
index = findfirst(iszero, epi.ky_lines) index = findfirst(iszero, epi.ky_lines)
if isnothing(index) if isnothing(index)
error("EPI readout does not pass through the centre of k-space") error("EPI readout does not pass through the centre of k-space")
end end
return effective_time(epi, index * 2) return variables.effective_time(epi, index * 2)
end end
function get_index_single_TR(epi::EPIReadout, index::Integer) function get_index_single_TR(epi::EPIReadout, index::Integer)
...@@ -101,7 +103,7 @@ function walk_pathway!(epi::EPIReadout, walker::PathwayWalker, pulse_effects::Ve ...@@ -101,7 +103,7 @@ function walk_pathway!(epi::EPIReadout, walker::PathwayWalker, pulse_effects::Ve
if nreadout[] > 0 if nreadout[] > 0
return false return false
end end
update_walker_till_time!(walker, block_start_time + effective_time(epi)) update_walker_till_time!(walker, block_start_time + variables.effective_time(epi))
return true return true
end end
......
...@@ -8,7 +8,7 @@ import ..EPIReadouts: EPIReadout ...@@ -8,7 +8,7 @@ import ..EPIReadouts: EPIReadout
import ...BuildSequences: global_model, build_sequence, global_scanner import ...BuildSequences: global_model, build_sequence, global_scanner
import ...Containers: Sequence import ...Containers: Sequence
import ...Components: SincPulse, ConstantPulse, InstantPulse, SingleReadout, InstantGradient import ...Components: SincPulse, ConstantPulse, InstantPulse, SingleReadout, InstantGradient
import ...Variables: qvec, flat_time, rise_time, qval, apply_simple_constraint!, variables import ...Variables: variables
function _get_pulse(shape, flip_angle, phase, frequency, Nzeros, group, bandwidth, duration) function _get_pulse(shape, flip_angle, phase, frequency, Nzeros, group, bandwidth, duration)
......
module SliceSelectRephases module SliceSelectRephases
import ...Containers: BaseSequence, get_index_single_TR import ...Containers: BaseSequence, get_index_single_TR
import ..Trapezoids: SliceSelect, Trapezoid import ..Trapezoids: SliceSelect, Trapezoid
import ...Variables: get_pulse, qval, apply_simple_constraint!, effective_time import ...Variables: get_pulse, apply_simple_constraint!, variables, @defvar
import ...Components: RFPulseComponent import ...Components: RFPulseComponent
""" """
...@@ -34,6 +34,6 @@ end ...@@ -34,6 +34,6 @@ end
get_index_single_TR(ss::SliceSelectRephase, ::Val{1}) = ss.slice_select get_index_single_TR(ss::SliceSelectRephase, ::Val{1}) = ss.slice_select
get_index_single_TR(ss::SliceSelectRephase, ::Val{2}) = ss.rephase get_index_single_TR(ss::SliceSelectRephase, ::Val{2}) = ss.rephase
get_pulse(ssr::SliceSelectRephase) = ssr.slice_select get_pulse(ssr::SliceSelectRephase) = ssr.slice_select
effective_time(ssr::SliceSelectRephase) = effective_time(ssr, 1) @defvar effective_time(ssr::SliceSelectRephase) = variables.effective_time(ssr, 1)
end end
\ No newline at end of file
...@@ -4,7 +4,7 @@ import LinearAlgebra: norm ...@@ -4,7 +4,7 @@ import LinearAlgebra: norm
import StaticArrays: SVector import StaticArrays: SVector
import JuMP: @constraint, @objective, objective_function import JuMP: @constraint, @objective, objective_function
import ...BuildSequences: global_model, global_scanner import ...BuildSequences: global_model, global_scanner
import ...Variables: VariableType, duration, rise_time, flat_time, effective_time, qval, gradient_strength, slew_rate, inverse_slice_thickness, get_free_variable, get_pulse, set_simple_constraints!, gradient_orientation import ...Variables: VariableType, get_pulse, set_simple_constraints!, variables, @defvar
import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent
import ...Containers: BaseBuildingBlock import ...Containers: BaseBuildingBlock
...@@ -92,9 +92,11 @@ function SpoiltSliceSelect(pulse::RFPulseComponent; orientation=[0, 0, 1], group ...@@ -92,9 +92,11 @@ function SpoiltSliceSelect(pulse::RFPulseComponent; orientation=[0, 0, 1], group
return res return res
end end
gradient_orientation(spoilt::SpoiltSliceSelect) = spoilt.orientation @defvar begin
duration_trap1(spoilt::SpoiltSliceSelect) = 2 * spoilt.rise_time1 + spoilt.flat_time1 - spoilt.diff_time gradient_orientation(spoilt::SpoiltSliceSelect) = spoilt.orientation
duration_trap2(spoilt::SpoiltSliceSelect) = 2 * spoilt.fall_time2 + spoilt.flat_time2 - spoilt.diff_time duration_trap1(spoilt::SpoiltSliceSelect) = 2 * spoilt.rise_time1 + spoilt.flat_time1 - spoilt.diff_time
duration_trap2(spoilt::SpoiltSliceSelect) = 2 * spoilt.fall_time2 + spoilt.flat_time2 - spoilt.diff_time
end
Base.keys(::SpoiltSliceSelect) = Val.((:rise1, :flat1, :fall1, :flat_pulse, :pulse, :rise2, :flat2, :fall2)) Base.keys(::SpoiltSliceSelect) = Val.((:rise1, :flat1, :fall1, :flat_pulse, :pulse, :rise2, :flat2, :fall2))
Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:rise1}) = ChangingGradient(0., slew_rate(spoilt), gradient_orientation(spoilt), rise_time(spoilt)[1], spoilt.group) Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:rise1}) = ChangingGradient(0., slew_rate(spoilt), gradient_orientation(spoilt), rise_time(spoilt)[1], spoilt.group)
...@@ -106,16 +108,19 @@ Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:rise2}) = ChangingGradient(slew_ ...@@ -106,16 +108,19 @@ Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:rise2}) = ChangingGradient(slew_
Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:flat2}) = ConstantGradient(slew_rate(spoilt) * fall_time(spoilt)[2], gradient_orientation(spoilt), flat_time(spoilt)[2], spoilt.group) Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:flat2}) = ConstantGradient(slew_rate(spoilt) * fall_time(spoilt)[2], gradient_orientation(spoilt), flat_time(spoilt)[2], spoilt.group)
Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:fall2}) = ChangingGradient(slew_rate(spoilt) * fall_time(spoilt)[2], -slew_rate(spoilt), gradient_orientation(spoilt), fall_time(spoilt)[2], spoilt.group) Base.getindex(spoilt::SpoiltSliceSelect, ::Val{:fall2}) = ChangingGradient(slew_rate(spoilt) * fall_time(spoilt)[2], -slew_rate(spoilt), gradient_orientation(spoilt), fall_time(spoilt)[2], spoilt.group)
rise_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1, spoilt.fall_time2 - spoilt.diff_time) @defvar begin
flat_time(spoilt::SpoiltSliceSelect) = (spoilt.flat_time1, spoilt.flat_time2) rise_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1, spoilt.fall_time2 - spoilt.diff_time)
fall_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1 - spoilt.diff_time, spoilt.fall_time2) flat_time(spoilt::SpoiltSliceSelect) = (spoilt.flat_time1, spoilt.flat_time2)
duration(spoilt::SpoiltSliceSelect) = sum(rise_time(spoilt)) + sum(flat_time(spoilt)) + sum(flat_time(spoilt)) + duration(spoilt.pulse) fall_time(spoilt::SpoiltSliceSelect) = (spoilt.rise_time1 - spoilt.diff_time, spoilt.fall_time2)
slew_rate(spoilt::SpoiltSliceSelect) = spoilt.slew_rate duration(spoilt::SpoiltSliceSelect) = sum(rise_time(spoilt)) + sum(flat_time(spoilt)) + sum(flat_time(spoilt)) + duration(spoilt.pulse)
inverse_slice_thickness(spoilt::SpoiltSliceSelect) = spoilt.slew_rate * spoilt.diff_time * duration(spoilt.pulse) * 1e3 slew_rate(spoilt::SpoiltSliceSelect) = spoilt.slew_rate
gradient_strength(spoilt::SpoiltSliceSelect) = slew_rate(spoilt) * max(spoilt.rise_time1, spoilt.fall_time2) inverse_slice_thickness(spoilt::SpoiltSliceSelect) = spoilt.slew_rate * spoilt.diff_time * duration(spoilt.pulse) * 1e3
gradient_strength(spoilt::SpoiltSliceSelect) = slew_rate(spoilt) * max(spoilt.rise_time1, spoilt.fall_time2)
end
get_pulse(spoilt::SpoiltSliceSelect) = spoilt.pulse get_pulse(spoilt::SpoiltSliceSelect) = spoilt.pulse
function all_gradient_strengths(spoilt::SpoiltSliceSelect) @defvar function all_gradient_strengths(spoilt::SpoiltSliceSelect)
grad1 = spoilt.slew_rate * rise_time(spoilt)[1] grad1 = spoilt.slew_rate * rise_time(spoilt)[1]
grad2 = grad1 - spoilt.slew_rate * flat_time(spoilt)[1] grad2 = grad1 - spoilt.slew_rate * flat_time(spoilt)[1]
grad3 = spoilt.slew_rate * fall_time(spoilt)[2] grad3 = spoilt.slew_rate * fall_time(spoilt)[2]
......
...@@ -6,8 +6,7 @@ module Trapezoids ...@@ -6,8 +6,7 @@ module Trapezoids
import JuMP: @constraint import JuMP: @constraint
import StaticArrays: SVector import StaticArrays: SVector
import LinearAlgebra: norm import LinearAlgebra: norm
import ...Variables: qval, rise_time, flat_time, slew_rate, gradient_strength, variables, duration, δ, get_free_variable, VariableType, inverse_bandwidth, effective_time, duration, set_simple_constraints!, scanner_constraints!, inverse_slice_thickness import ...Variables: variables, @defvar, scanner_constraints!, get_free_variable, set_simple_constraints!, gradient_orientation, VariableType
import ...Variables: Variables, all_variables_symbols, dwell_time, inverse_fov, inverse_voxel_size, fov, voxel_size, get_gradient, get_pulse, get_readout, gradient_orientation, ramp_overlap, adjustable, adjust_internal
import ...BuildSequences: global_model import ...BuildSequences: global_model
import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent, ADC import ...Components: ChangingGradient, ConstantGradient, RFPulseComponent, ADC
import ...Containers: BaseBuildingBlock import ...Containers: BaseBuildingBlock
...@@ -107,14 +106,16 @@ gradient_orientation(pg::Trapezoid{1}) = pg.orientation ...@@ -107,14 +106,16 @@ gradient_orientation(pg::Trapezoid{1}) = pg.orientation
get_group(pg::Trapezoid) = pg.group get_group(pg::Trapezoid) = pg.group
get_group(pg::BaseTrapezoid) = get_group(get_gradient(pg)) get_group(pg::BaseTrapezoid) = get_group(get_gradient(pg))
rise_time(pg::Trapezoid) = pg.rise_time @defvar begin
flat_time(pg::Trapezoid) = pg.flat_time rise_time(pg::Trapezoid) = pg.rise_time
gradient_strength(g::Trapezoid) = slew_rate(g) .* rise_time(g) flat_time(pg::Trapezoid) = pg.flat_time
slew_rate(g::Trapezoid) = g.slew_rate gradient_strength(g::Trapezoid) = slew_rate(g) .* rise_time(g)
δ(g::Trapezoid) = rise_time(g) + flat_time(g) slew_rate(g::Trapezoid) = g.slew_rate
duration(g::BaseTrapezoid) = 2 * rise_time(g) + flat_time(g) diffusion_time(g::Trapezoid) = rise_time(g) + flat_time(g)
duration(g::BaseTrapezoid) = 2 * rise_time(g) + flat_time(g)
qval(g::BaseTrapezoid, ::Nothing, ::Nothing) = δ(g) .* gradient_strength(g) .* 2π qval(g::BaseTrapezoid, ::Nothing, ::Nothing) = δ(g) .* gradient_strength(g) .* 2π
end
adjustable(::BaseTrapezoid) = :gradient adjustable(::BaseTrapezoid) = :gradient
...@@ -176,11 +177,11 @@ end ...@@ -176,11 +177,11 @@ end
Base.keys(::SliceSelect) = (Val(:rise), Val(:flat), Val(:pulse), Val(:fall)) Base.keys(::SliceSelect) = (Val(:rise), Val(:flat), Val(:pulse), Val(:fall))
Base.getindex(pg::SliceSelect, ::Val{:pulse}) = (0., pg.pulse) Base.getindex(pg::SliceSelect, ::Val{:pulse}) = (0., pg.pulse)
inverse_slice_thickness(ss::SliceSelect) = 1e3 * gradient_strength(ss.trapezoid) .* inverse_bandwidth(ss.pulse) @defvar inverse_slice_thickness(ss::SliceSelect) = 1e3 * variables.gradient_strength(ss.trapezoid) .* variables.inverse_bandwidth(ss.pulse)
get_pulse(ss::SliceSelect) = ss.pulse get_pulse(ss::SliceSelect) = ss.pulse
get_gradient(ss::SliceSelect) = ss.trapezoid get_gradient(ss::SliceSelect) = ss.trapezoid
effective_time(ss::SliceSelect) = effective_time(ss, :pulse) @defvar effective_time(ss::SliceSelect) = variables.effective_time(ss, :pulse)
""" """
LineReadout(adc; ramp_overlap=1., orientation=nothing, group=nothing, variables...) LineReadout(adc; ramp_overlap=1., orientation=nothing, group=nothing, variables...)
...@@ -221,10 +222,12 @@ end ...@@ -221,10 +222,12 @@ end
Base.keys(::LineReadout) = (Val(:rise), Val(:adc), Val(:flat), Val(:fall)) Base.keys(::LineReadout) = (Val(:rise), Val(:adc), Val(:flat), Val(:fall))
Base.getindex(lr::LineReadout, ::Val{:adc}) = ((1 - ramp_overlap(lr)) * rise_time(lr), lr.adc) Base.getindex(lr::LineReadout, ::Val{:adc}) = ((1 - ramp_overlap(lr)) * rise_time(lr), lr.adc)
ramp_overlap(lr::LineReadout) = lr.ramp_overlap @defvar begin
inverse_fov(lr::LineReadout) = 1e3 * dwell_time(lr.adc) * gradient_strength(lr.trapezoid) * lr.adc.oversample ramp_overlap(lr::LineReadout) = lr.ramp_overlap
inverse_voxel_size(lr::LineReadout) = 1e3 * duration(lr.adc) * gradient_strength(lr.trapezoid) inverse_fov(lr::LineReadout) = 1e3 * dwell_time(lr.adc) * gradient_strength(lr.trapezoid) * lr.adc.oversample
effective_time(lr::LineReadout) = effective_time(lr, :adc) inverse_voxel_size(lr::LineReadout) = 1e3 * duration(lr.adc) * gradient_strength(lr.trapezoid)
effective_time(lr::LineReadout) = variables.effective_time(lr, :adc)
end
get_readout(lr::LineReadout) = lr.adc get_readout(lr::LineReadout) = lr.adc
get_gradient(lr::LineReadout) = lr.trapezoid get_gradient(lr::LineReadout) = lr.trapezoid
......
module Plot module Plot
import MakieCore: generic_plot_attributes! import MakieCore: generic_plot_attributes!
import ..Containers: BaseBuildingBlock, BaseSequence, waveform, events, start_time, ndim_grad, waveform_sequence import ..Containers: BaseBuildingBlock, BaseSequence, waveform, events, start_time, ndim_grad, waveform_sequence
import ..Variables: duration, flip_angle, phase, make_generic, gradient_orientation import ..Variables: make_generic, gradient_orientation, variables
import ..Components: RFPulseComponent, ADC, InstantPulse, NoGradient, InstantGradient1D, InstantGradient3D import ..Components: RFPulseComponent, ADC, InstantPulse, NoGradient, InstantGradient1D, InstantGradient3D
""" """
...@@ -16,7 +16,7 @@ struct SinglePlotLine ...@@ -16,7 +16,7 @@ struct SinglePlotLine
event_amplitudes :: Vector{Float64} event_amplitudes :: Vector{Float64}
end end
duration(pl::SinglePlotLine) = iszero(length(pl.times)) ? 0. : pl.times[end] duration_line(pl::SinglePlotLine) = iszero(length(pl.times)) ? 0. : pl.times[end]
SinglePlotLine(times::Vector{Float64}, amplitudes::Vector{Float64}) = SinglePlotLine(times, amplitudes, Float64[], Float64[]) SinglePlotLine(times::Vector{Float64}, amplitudes::Vector{Float64}) = SinglePlotLine(times, amplitudes, Float64[], Float64[])
function SinglePlotLine(control_points::AbstractVector{<:Tuple}, duration::Number) function SinglePlotLine(control_points::AbstractVector{<:Tuple}, duration::Number)
...@@ -45,7 +45,7 @@ function SinglePlotLine(plot_lines::SinglePlotLine...) ...@@ -45,7 +45,7 @@ function SinglePlotLine(plot_lines::SinglePlotLine...)
append!(amplitudes, pl.amplitudes) append!(amplitudes, pl.amplitudes)
append!(event_times, pl.event_times .+ current_time) append!(event_times, pl.event_times .+ current_time)
append!(event_amplitudes, pl.event_amplitudes) append!(event_amplitudes, pl.event_amplitudes)
current_time += duration(pl) current_time += duration_line(pl)
end end
return SinglePlotLine(times, amplitudes, event_times, event_amplitudes) return SinglePlotLine(times, amplitudes, event_times, event_amplitudes)
end end
...@@ -119,7 +119,7 @@ function SequenceDiagram(bbb::BaseBuildingBlock) ...@@ -119,7 +119,7 @@ function SequenceDiagram(bbb::BaseBuildingBlock)
if !all([wvs isa NoGradient for (_, wvs) in waveform_sequence(bbb)]) if !all([wvs isa NoGradient for (_, wvs) in waveform_sequence(bbb)])
orientation = ndim_grad(bbb) == 3 ? 1. : gradient_orientation(bbb) orientation = ndim_grad(bbb) == 3 ? 1. : gradient_orientation(bbb)
for (index, symbol) in enumerate((:Gx, :Gy, :Gz)) for (index, symbol) in enumerate((:Gx, :Gy, :Gz))
kwargs[symbol] = SinglePlotLine([(time, (orientation .* amplitude)[index]) for (time, amplitude) in waveform(bbb)], duration(bbb)) kwargs[symbol] = SinglePlotLine([(time, (orientation .* amplitude)[index]) for (time, amplitude) in waveform(bbb)], variables.duration(bbb))
end end
end end
...@@ -132,7 +132,7 @@ function SequenceDiagram(bbb::BaseBuildingBlock) ...@@ -132,7 +132,7 @@ function SequenceDiagram(bbb::BaseBuildingBlock)
end end
for (symbol, fn) in [(:RFx, cosd), (:RFy, sind)] for (symbol, fn) in [(:RFx, cosd), (:RFy, sind)]
if event isa InstantPulse if event isa InstantPulse
kwargs[symbol] = SinglePlotLine([0., duration(bbb)], [0., 0.], [delay], [flip_angle(event) * fn(phase(event))]) kwargs[symbol] = SinglePlotLine([0., variables.duration(bbb)], [0., 0.], [delay], [variables.flip_angle(event) * fn(variables.phase(event))])
else else
points = Tuple{Float64, Float64}[] points = Tuple{Float64, Float64}[]
t_prev = p_prev = a_prev = nothing t_prev = p_prev = a_prev = nothing
...@@ -154,34 +154,34 @@ function SequenceDiagram(bbb::BaseBuildingBlock) ...@@ -154,34 +154,34 @@ function SequenceDiagram(bbb::BaseBuildingBlock)
p_prev = p p_prev = p
a_prev = a a_prev = a
end end
kwargs[symbol] = SinglePlotLine(points, duration(bbb)) kwargs[symbol] = SinglePlotLine(points, variables.duration(bbb))
end end
end end
elseif event isa ADC elseif event isa ADC
if :ADC in keys(kwargs) if :ADC in keys(kwargs)
error("Cannot plot a building block with more than 1 ADC event.") error("Cannot plot a building block with more than 1 ADC event.")
end end
if iszero(duration(event)) if iszero(variables.duration(event))
kwargs[:ADC] = SinglePlotLine( kwargs[:ADC] = SinglePlotLine(
[0., duration(bbb)], [0., variables.duration(bbb)],
[0., 0.], [0., 0.],
[delay], [1.] [delay], [1.]
) )
else else
kwargs[:ADC] = SinglePlotLine( kwargs[:ADC] = SinglePlotLine(
[0., delay, delay, delay + duration(event), delay + duration(event), duration(bbb)], [0., delay, delay, delay + variables.duration(event), delay + variables.duration(event), variables.duration(bbb)],
[0., 0., 1., 1., 0., 0.], [0., 0., 1., 1., 0., 0.],
) )
end end
elseif event isa InstantGradient1D elseif event isa InstantGradient1D
kwargs[:G] = SinglePlotLine([0., duration(bbb)], [0., 0.], [delay], [event.qval]) kwargs[:G] = SinglePlotLine([0., variables.duration(bbb)], [0., 0.], [delay], [event.qval])
elseif event isa InstantGradient3D elseif event isa InstantGradient3D
for (index, symbol) in enumerate([:Gx, :Gy, :Gz]) for (index, symbol) in enumerate([:Gx, :Gy, :Gz])
kwargs[symbol] = SinglePlotLine([0., duration(bbb)], [0., 0.], [delay], [event.qval[index]]) kwargs[symbol] = SinglePlotLine([0., variables.duration(bbb)], [0., 0.], [delay], [event.qval[index]])
end end
end end
end end
return SequenceDiagram(duration(bbb); kwargs...) return SequenceDiagram(variables.duration(bbb); kwargs...)
end end
function SequenceDiagram(seq::BaseSequence) function SequenceDiagram(seq::BaseSequence)
......
module Printing module Printing
import JuMP: value import JuMP: value
import Printf: @sprintf import Printf: @sprintf
import ..Variables: VariableType, variables, AbstractBlock, VariableNotAvailable, alternative_variables import ..Variables: VariableType, variables, AbstractBlock
function _robust_value(possible_number::VariableType) function _robust_value(possible_number::VariableType)
try try
...@@ -47,20 +46,14 @@ function Base.show(io::IO, block::AbstractBlock) ...@@ -47,20 +46,14 @@ function Base.show(io::IO, block::AbstractBlock)
end end
for fn in values(variables) for fn in values(variables)
if fn in [fn_alt for (fn_alt, _, _, _) in values(alternative_variables)]
continue
end
try try
numeric_value = _robust_value(fn(block)) numeric_value = _robust_value(fn(block))
if isnothing(numeric_value) if isnothing(numeric_value)
continue continue
end end
print(io, "$(nameof(fn))=$(numeric_value), ") print(io, "$(nameof(fn))=$(numeric_value), ")
catch e catch
if e isa VariableNotAvailable continue
continue
end
rethrow()
end end
end end
print(io, ")") print(io, ")")
......
...@@ -7,7 +7,7 @@ import ..PulseqIO.Types: PulseqSequence, PulseqBlock, PulseqTrapezoid, PulseqGra ...@@ -7,7 +7,7 @@ import ..PulseqIO.Types: PulseqSequence, PulseqBlock, PulseqTrapezoid, PulseqGra
import ...Containers: Sequence, BuildingBlock, BaseBuildingBlock, events, waveform, iter_blocks import ...Containers: Sequence, BuildingBlock, BaseBuildingBlock, events, waveform, iter_blocks
import ...Components: GenericPulse, ADC, RFPulseComponent import ...Components: GenericPulse, ADC, RFPulseComponent
import ...Scanners: Scanner import ...Scanners: Scanner
import ...Variables: duration, nsamples, dwell_time, make_generic import ...Variables: variables, make_generic
function Sequence(pulseq::PulseqSequence; scanner=nothing, B0=nothing) function Sequence(pulseq::PulseqSequence; scanner=nothing, B0=nothing)
if isnothing(scanner) if isnothing(scanner)
...@@ -145,8 +145,8 @@ function PulseqBlock(block::BaseBuildingBlock; BlockDurationRaster, AdcRasterTim ...@@ -145,8 +145,8 @@ function PulseqBlock(block::BaseBuildingBlock; BlockDurationRaster, AdcRasterTim
error("Pulseq does not support a single building block containing multiple ADC events.") error("Pulseq does not support a single building block containing multiple ADC events.")
end end
adc = PulseqADC( adc = PulseqADC(
nsamples(event), variables.nsamples(event),
div(dwell_time(event), AdcRasterTime, RoundNearest), div(variables.dwell_time(event), AdcRasterTime, RoundNearest),
Int(div(delay, 1e-3, RoundNearest)), Int(div(delay, 1e-3, RoundNearest)),
0., 0. 0., 0.
) )
......
...@@ -2,7 +2,7 @@ module DiffusionSpinEchoes ...@@ -2,7 +2,7 @@ module DiffusionSpinEchoes
import ...Containers: Sequence import ...Containers: Sequence
import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler, refocus_pulse, dwi_gradients import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler, refocus_pulse, dwi_gradients
import ...Containers: start_time import ...Containers: start_time
import ...Variables: get_pulse, get_readout, echo_time, duration_transverse, delay, effective_time, diffusion_time, Δ, TR, TE, repetition_time, get_gradient import ...Variables: get_pulse, get_readout, get_gradient, variables, @defvar
import ...Pathways: Pathway, get_pathway import ...Pathways: Pathway, get_pathway
import ...BuildSequences: build_sequence import ...BuildSequences: build_sequence
import ...Scanners: Default_Scanner import ...Scanners: Default_Scanner
...@@ -64,8 +64,11 @@ get_pulse(ge::DiffusionSpinEcho) = (excitation=ge[:excitation], refocus=ge[:refo ...@@ -64,8 +64,11 @@ get_pulse(ge::DiffusionSpinEcho) = (excitation=ge[:excitation], refocus=ge[:refo
get_gradient(ge::DiffusionSpinEcho) = (gradient=ge[:gradient], gradient2=ge[:gradient2]) get_gradient(ge::DiffusionSpinEcho) = (gradient=ge[:gradient], gradient2=ge[:gradient2])
get_readout(ge::DiffusionSpinEcho) = ge.readout get_readout(ge::DiffusionSpinEcho) = ge.readout
get_pathway(ge::DiffusionSpinEcho) = Pathway(ge, [90, 180], 1, group=:diffusion) get_pathway(ge::DiffusionSpinEcho) = Pathway(ge, [90, 180], 1, group=:diffusion)
echo_time(ge::DiffusionSpinEcho) = 2 * (effective_time(ge, :refocus) - effective_time(ge, :excitation))
delay(ge::DiffusionSpinEcho) = duration_transverse(ge) - echo_time(ge) @defvar begin
diffusion_time(ge::DiffusionSpinEcho) = start_time(ge, :gradient2) - start_time(ge, :gradient) echo_time(ge::DiffusionSpinEcho) = 2 * (effective_time(ge, :refocus) - variables.effective_time(ge, :excitation))
delay(ge::DiffusionSpinEcho) = variables.duration_transverse(ge) - variables.echo_time(ge)
diffusion_time(ge::DiffusionSpinEcho) = start_time(ge, :gradient2) - start_time(ge, :gradient)
end
end end
\ No newline at end of file
module GradientEchoes module GradientEchoes
import ...Containers: Sequence import ...Containers: Sequence
import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler
import ...Variables: get_pulse, get_readout, echo_time, duration_transverse, TR, TE, repetition_time import ...Variables: get_pulse, get_readout, variables, @defvar
import ...Pathways: Pathway, get_pathway import ...Pathways: Pathway, get_pathway
import ...BuildSequences: build_sequence import ...BuildSequences: build_sequence
import ...Scanners: Default_Scanner import ...Scanners: Default_Scanner
...@@ -47,7 +47,7 @@ end ...@@ -47,7 +47,7 @@ end
get_pulse(ge::GradientEcho) = ge.excitation get_pulse(ge::GradientEcho) = ge.excitation
get_readout(ge::GradientEcho) = ge.readout get_readout(ge::GradientEcho) = ge.readout
get_pathway(ge::GradientEcho) = Pathway(ge, [90], 1) get_pathway(ge::GradientEcho) = Pathway(ge, [90], 1)
echo_time(ge::GradientEcho) = duration_transverse(ge) @defvar echo_time(ge::GradientEcho) = variables.duration_transverse(ge)
......
module SpinEchoes module SpinEchoes
import ...Containers: Sequence import ...Containers: Sequence
import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler, refocus_pulse import ...Parts: excitation_pulse, readout_event, interpret_image_size, Trapezoid, gradient_spoiler, refocus_pulse
import ...Variables: get_pulse, get_readout, echo_time, duration_transverse, delay, effective_time, TR, TR, repetition_time import ...Variables: get_pulse, get_readout, variables, @defvar
import ...Pathways: Pathway, get_pathway import ...Pathways: Pathway, get_pathway
import ...BuildSequences: build_sequence import ...BuildSequences: build_sequence
import ...Scanners: Default_Scanner import ...Scanners: Default_Scanner
...@@ -51,8 +51,11 @@ end ...@@ -51,8 +51,11 @@ end
get_pulse(ge::SpinEcho) = (excitation=ge.excitation, refocus=ge.refocus) get_pulse(ge::SpinEcho) = (excitation=ge.excitation, refocus=ge.refocus)
get_readout(ge::SpinEcho) = ge.readout get_readout(ge::SpinEcho) = ge.readout
get_pathway(ge::SpinEcho) = Pathway(ge, [90, 180], 1) get_pathway(ge::SpinEcho) = Pathway(ge, [90, 180], 1)
echo_time(ge::SpinEcho) = 2 * (effective_time(ge, :refocus) - effective_time(ge, :excitation))
delay(ge::SpinEcho) = duration_transverse(ge) - echo_time(ge) @defvar begin
echo_time(ge::SpinEcho) = 2 * (variables.effective_time(ge, :refocus) - variables.effective_time(ge, :excitation))
delay(ge::SpinEcho) = variables.duration_transverse(ge) - variables.echo_time(ge)
end
end end
\ No newline at end of file
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