From 65d76dcc3c8c76aa8b872af92735ecc3a783befe Mon Sep 17 00:00:00 2001 From: Michiel Cottaar <michiel.cottaar@ndcn.ox.ac.uk> Date: Tue, 20 Feb 2024 18:53:57 +0000 Subject: [PATCH] Treat pathway values as variables --- src/MRIBuilder.jl | 4 ++-- src/pathways.jl | 61 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/MRIBuilder.jl b/src/MRIBuilder.jl index cf2f428..ec1160c 100644 --- a/src/MRIBuilder.jl +++ b/src/MRIBuilder.jl @@ -27,8 +27,8 @@ export InstantPulse, ConstantPulse, SincPulse, GenericPulse, InstantGradient, Si 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 .Pathways: Pathway, duration_transverse, duration_dephase, bval, bmat -export Pathway, duration_transverse, duration_dephase, bval, bmat +import .Pathways: Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway +export Pathway, duration_transverse, duration_dephase, bval, bmat, get_pathway import .Parts: excitation_pulse, refocus_pulse, epi_readout, single_line_readout, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout export excitation_pulse, refocus_pulse, epi_readout, single_line_readout, Trapezoid, SliceSelect, LineReadout, opposite_kspace_lines, SpoiltSliceSelect, SliceSelectRephase, EPIReadout diff --git a/src/pathways.jl b/src/pathways.jl index 1724950..3e020fe 100644 --- a/src/pathways.jl +++ b/src/pathways.jl @@ -3,7 +3,7 @@ import LinearAlgebra: norm, tr import StaticArrays: SVector, SMatrix import ..Components: NoGradient, RFPulseComponent, ReadoutComponent, InstantGradient, GradientWaveform, DelayedEvent import ..Containers: BaseSequence, Sequence, BaseBuildingBlock, waveform, events, waveform_sequence, start_time, AlternativeBlocks -import ..Variables: qvec, qval, bmat_gradient, VariableType, effective_time, duration, TR +import ..Variables: qvec, qval, bmat_gradient, VariableType, effective_time, duration, TR, variables """ @@ -112,54 +112,81 @@ end """ - qvec(pathway::Pathway; group=nothing) + qvec(pathway::Pathway) Return net displacement vector in k-space/q-space experienced by the spins following a specific [`Pathway`](@ref). Only gradients active while the spins are in the transverse plane are considered. -By default gradients that have been added to a specific `group` are ignored. -You can set `group=<name>` to consider a specific `group. +Returns a NamedTuple with the `qvec` for all gradient groups. """ -qvec(pathway::Pathway; group=nothing) = get(pathway.qvec, group, zero(SVector{3, Float64})) +qvec(pathway::Pathway, group) = pathway.qvec[group] """ - area_under_curve(pathway::Pathway; group=nothing) + area_under_curve(pathway::Pathway) Return net displacement in k-space (i.e., spoiling) experienced by the spins following a specific [`Pathway`](@ref). Only gradients active while the spins are in the transverse plane are considered. -By default gradients that have been added to a specific `group` are ignored. -You can set `group=<name>` to consider a specific `group. +Returns a NamedTuple with the `area_under_curve` for all gradient groups. """ -area_under_curve(pathway::Pathway; group=nothing) = qval(pathway; group=group) +area_under_curve(pathway::Pathway, group) = norm(qvec(pathway, group)) """ - bmat(pathway::Pathway; group=nothing) + bmat(pathway::Pathway) Return 3x3 diffusion-weighted matrix experienced by the spins following a specific [`Pathway`](@ref) in rad^2 ms/um^2. Only gradients active while the spins are in the transverse plane are considered. -By default gradients that have been added to a specific `group` are ignored. -You can set `group=<name>` to consider a specific `group. +Returns a NamedTuple with the `bmat` for all gradient groups. """ -bmat(pathway::Pathway; group=nothing) = get(pathway.bmat, group, zero(SMatrix{3, 3, Float64, 9})) +bmat(pathway::Pathway, group) = pathway.bmat[group] """ - bval(pathway::Pathway; group=nothing) + bval(pathway::Pathway) Return size of diffusion-weighting experienced by the spins following a specific [`Pathway`](@ref) in rad^2 ms/um^2. Only gradients active while the spins are in the transverse plane will contribute to the diffusion weighting. -By default gradients that have been added to a specific `group` are ignored. -You can set `group=<name>` to consider a specific `group. +Returns a NamedTuple with the `bval` for all gradient groups. """ -bval(pathway::Pathway; group=nothing) = tr(bmat(pathway; group=group)) +bval(pathway::Pathway, group) = tr(bmat(pathway, group)) + + +""" + get_pathway(sequence) + +Gets the main [`PathWay`](@ref) that spins are expected to experience in the sequence. + +Multiple pathways might be returned as an array or (named)tuple. +""" +function get_pathway end + +for fn in (:qvec, :area_under_curve, :bmat, :bval) + @eval function $fn(pathway::Pathway) + return NamedTuple(group => $fn(pathway, group) for group in keys(pathway.qvec)) + end +end + +for fn in (:qvec, :area_under_curve, :bmat, :bval, :duration_dephase, :duration_transverse) + @eval function $fn(seq::Sequence) + pathway = get_pathway(seq) + if pathway isa Pathway + return $fn(pathway) + elseif pathway isa AbstractVector || pathway isa Tuple + return $fn.(pathway) + elseif pathway isa NumedTuple + return NamedTuple(k => $fn(v) for (k, v) in pairs(pathway)) + end + error("get_pathway returned unexpected type for $seq") + end + @eval variables[$(QuoteNode(fn))] = $fn +end """ -- GitLab