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

NoGradient should always be 0-dimensional

parent 80ce6d61
No related branches found
No related tags found
No related merge requests found
......@@ -2,17 +2,17 @@
Module defining sub-types of the [`GradientWaveform`](@ref).
There are only three types of [`GradientBlock`] objects:
- [`ChangingGradientBlock`](@ref): any gradient changing linearly in strength.
- [`ConstantGradientBlock`](@ref): any gradient staying constant in strength. These can overlap with a pulse (`SliceSelectPulse`).
- [`NoGradientBlock`](@ref): any part of the gradient waveform when no gradient is active.
- [`ChangingGradient`](@ref): any gradient changing linearly in strength.
- [`ConstantGradient`](@ref): any gradient staying constant in strength. These can overlap with a pulse (`SliceSelectPulse`).
- [`NoGradient`](@ref): any part of the gradient waveform when no gradient is active.
These parts are combined into a full gradient waveform in a `BuildingBlock`.
Each part of this gradient waveform can compute:
- [`gradient_strength`]: maximum gradient strength in each dimension.
- [`slew_rate`]: maximum slew rate in each dimension.
- [`qvec`]: area under curve in each dimension
- [`bmat_gradient`]: diffusion weighting (scalar in 1D or matrix in 3D).
- `gradient_strength`: maximum gradient strength in each dimension.
- `slew_rate`: maximum slew rate in each dimension.
- `qval`/`qval3`: area under curve
- `bmat_gradient`: diffusion weighting (scalar in 1D or matrix in 3D).
"""
module GradientWaveforms
......
......@@ -5,38 +5,26 @@ import ...AbstractTypes: GradientWaveform
import ..ChangingGradientBlocks: split_gradient
"""
NoGradient{N}(duration)
NoGradient(duration)
Part of a gradient waveform when there is no gradient active.
`N` needs to be set to 1 if `orientation` is fixed in the gradient waveform or 3 otherwise.
Usually, you do not want to create this object directly, use a `BuildingBlock` instead.
"""
struct NoGradient{N} <: GradientWaveform{N}
struct NoGradient <: GradientWaveform{0}
duration :: VariableType
function NoGradient{N}(duration) where {N}
if !(N in (1, 3))
error("Dimensionality of the gradient should be 1 or 3, not $N")
end
new(duration)
end
end
duration(ngb::NoGradient) = ngb.duration
for func in (:qval, :gradient_strength, :slew_rate)
@eval $func(::NoGradient{1}) = 0.
@eval $func(::NoGradient{3}) = zero(SVector{3, Float64})
@eval $func(::NoGradient) = 0.
end
gradient_strength(cgb::NoGradient, time::Number) = gradient_strength(cgb)
NoGradient(duration) = NoGradient{1}(duration)
gradient_strength(nb::NoGradient, time::Number) = 0.
bmat_gradient(::NoGradient{1}) = 0.
bmat_gradient(::NoGradient{3}) = zero(SMatrix{3, 3, Float64, 9})
bmat_gradient(ngb::NoGradient{1}, qstart::VariableType) = qstart^2 * duration(ngb)
bmat_gradient(ngb::NoGradient{3}, qstart::AbstractVector{<:VariableType}) = @. qstart * permutedims(qstart) * duration(ngb)
bmat_gradient(::NoGradient) = 0.
bmat_gradient(ngb::NoGradient, qstart::VariableType) = qstart^2 * duration(ngb)
bmat_gradient(ngb::NoGradient, qstart::AbstractVector{<:VariableType}) = @. qstart * permutedims(qstart) * duration(ngb)
function split_gradient(ngb::NoGradient, times::VariableType...)
durations = [times[1], [t[2] - t[1] for t in zip(times[1:end-1], times[2:end])]..., duration(ngb) - times[end]]
......
......@@ -173,7 +173,7 @@ Converst object into something that can be included in the sequence:
to_block(cb::ContainerBlock) = cb
to_block(s::Symbol) = to_block(Val(s))
to_block(s::Union{VariableType, Nothing, Val{:min}, Val{:max}}) = Wait(s)
to_block(ec::EventComponent) = BuildingBlock([NoGradient{3}(duration(ec)), (0., ec)])
to_block(ec::EventComponent) = BuildingBlock([NoGradient(duration(ec)), (0., ec)])
function make_generic(seq::BaseSequence)
......
......@@ -274,7 +274,6 @@ end
function BuildingBlock(waveform::AbstractVector, events::AbstractVector; orientation=nothing, group=nothing)
events = Any[events...]
waveform = Any[waveform...]
ndim = isnothing(orientation) ? 1 : 3
zero_grad = isnothing(orientation) ? zeros(3) : 0.
if length(waveform) == 0 || waveform[1][1] > 0.
pushfirst!(waveform, (0., zero_grad))
......@@ -284,7 +283,7 @@ function BuildingBlock(waveform::AbstractVector, events::AbstractVector; orienta
for (index_grad, ((prev_time, prev_grad), (time, grad))) in enumerate(zip(waveform[1:end-1], waveform[2:end]))
duration = time - prev_time
if norm(prev_grad) <= 1e-12 && norm(grad) <= 1e-12
push!(components, NoGradient{ndim}(duration))
push!(components, NoGradient(duration))
elseif norm(prev_grad) norm(grad)
push!(components, ConstantGradient(prev_grad, orientation, duration, group))
else
......@@ -352,6 +351,6 @@ end
duration(wb::Wait) = wb.duration
Base.keys(::Wait) = (Val(:empty),)
Base.getindex(wb::Wait, ::Val{:empty}) = NoGradient{1}(wb.duration)
Base.getindex(wb::Wait, ::Val{:empty}) = NoGradient(wb.duration)
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