From a8078c7b944443cf19a7712806c627ae40d2e7f2 Mon Sep 17 00:00:00 2001
From: Michiel Cottaar <MichielCottaar@protonmail.com>
Date: Thu, 30 May 2024 12:06:47 +0100
Subject: [PATCH] Document variables and @defvar

---
 src/variables.jl | 51 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/src/variables.jl b/src/variables.jl
index 444aa77..bcd4067 100644
--- a/src/variables.jl
+++ b/src/variables.jl
@@ -91,6 +91,20 @@ struct _Variables
     variables :: Dict{Symbol, AnyVariable}
 end
 
+"""
+Main interface to all the MRIBuilder sequence variables.
+
+All variables are available as members of this object, e.g.
+`variables.echo_time` returns the echo time variable.
+New variables can be defined using [`@defvar`](@ref).
+
+Set constraints on variables by passing them on as keywords during the sequence generation,
+e.g., `seq=SpinEcho(echo_time=70)`.
+
+After sequence generation you can get the variable values by calling
+`variables.echo_time(seq)`.
+For the sequence defined above this would return 70. (or a number very close to that).
+"""
 variables = _Variables(Dict{Symbol, AnyVariable}())
 
 Base.getindex(v::_Variables, i::Symbol) = getfield(v, :variables)[i]
@@ -102,6 +116,43 @@ Base.propertynames(v::_Variables) = Tuple(keys(getfield(v, :variables)))
 Base.getproperty(v::_Variables, s::Symbol) = v[s]
 
 
+"""
+    @defvar([getter, ], function(s))
+
+Defines new [`variables`](@ref).
+
+Each variable is defined as regular Julia functions embedded within a `@defvar` macro.
+For example, to define a `variables.echo_time` variable for a `SpinEcho` sequence, one can use:
+```julia
+@defvar echo_time(ge::SpinEcho) = 2 * (variables.effective_time(ge, :refocus) - variables.effective_time(ge, :excitation))
+```
+
+Multiple variables can be defined in a single `@defvar` by including them in a code block:
+```julia
+@defvar begin
+    function var1(seq::SomeSequenceType)
+        ...
+    end
+    function var2(seq::SomeSequenceType)
+        ...
+    end
+end
+```
+
+Before the variable function definitions one can include a `getter`.
+This `getter` defines the type of the sequence component for which the variables will be defined.
+If the variable is not defined for the sequence, the variable will be extracted for those type of sequence components instead.
+The following sequence component types are provided:
+- `pulse`: use [`get_pulse`](@ref)
+- `gradient`: use [`get_gradient`](@ref)
+- `readout`: use [`get_readout`](@ref)
+- `pathway`: use [`get_pathway`](@ref)
+e.g. the following defines a `flip_angle` variable, which is marked as a property of an RF pulse.
+```julia
+@defvar pulse flip_angle(...) = ...
+```
+If after this definition, `flip_angle` is not explicitly defined for any sequence, it will be extracted for the RF pulses in that sequence instead.
+"""
 macro defvar(func_def) 
     return _defvar(func_def, nothing)
 end
-- 
GitLab