Automatic differentiation
This page shows how to use Automatic Differentiation in combination with an EPG simulation.
The AD package tested is ForwardDiff.jl, maybe it works with others with some minor modification to the following code.
Load package
using EPGsim, ForwardDiff, CairoMakie
Building signal function
function MESE_EPG(T2,T1,TE,ETL,delta)
+Automatic Differentiation · EPGsim.jl Automatic differentiation
This page shows how to use Automatic Differentiation in combination with an EPG simulation.
The AD package tested is ForwardDiff.jl, maybe it works with others with some minor modification to the following code.
Load package
using EPGsim, ForwardDiff, CairoMakie
Building signal function
function MESE_EPG(T2,T1,TE,ETL,delta)
T = eltype(complex(T2))
E = EPGStates([T(0.0)],[T(0.0)],[T(1.0)])
echo_vec = Vector{Complex{eltype(T2)}}()
@@ -63,7 +63,46 @@
lines!(ax,TE_vec,abs.(amp))
ax = Axis(f[1,2], title = "AD of MESE signal with B1 = $(deltaB1)",xlabel="TE [ms]")
lines!(ax,TE_vec,df)
-f
Reproducibility
This page was generated with the following version of Julia:
using InteractiveUtils
+f
Differentiation along multiple variables
If we want to obtain the derivation along T1 and T2 we need to change the EPG_MESE function. The function should take as input a vector containing T2 and T1 (here noted T2/T1) :
function MESE_EPG2(T2T1,TE,ETL,delta)
+ T2,T1 = T2T1
+ T = complex(eltype(T2))
+ E = EPGStates([T(0.0)],[T(0.0)],[T(1.0)])
+ echo_vec = Vector{Complex{eltype(T2)}}()
+
+ E = epgRotation(E,pi/2*delta, pi/2)
+ ##loop over refocusing-pulses
+ for i = 1:ETL
+ E = epgDephasing(E,1)
+ E = epgRelaxation(E,TE,T1,T2)
+ E = epgRotation(E,pi*delta,0.0)
+ E = epgDephasing(E,1)
+ push!(echo_vec,E.Fp[1])
+ end
+
+ return abs.(echo_vec)
+end
+
+j2 = ForwardDiff.jacobian(x -> MESE_EPG2(x,TE,ETL,deltaB1),[T2,T1])
50×2 Matrix{Float64}:
+ 0.00148849 0.0
+ 0.00267849 1.01626e-6
+ 0.0036074 3.11376e-9
+ 0.00424856 1.4929e-6
+ 0.0048583 2.1588e-7
+ 0.00505738 1.54224e-6
+ 0.00547205 4.77635e-7
+ 0.0053872 1.48187e-6
+ 0.00561831 5.69176e-7
+ 0.00541662 1.50582e-6
+ ⋮
+ 0.000653146 6.78462e-7
+ 0.000604545 -4.24151e-7
+ 0.000549214 6.53958e-7
+ 0.000506571 -4.35399e-7
+ 0.000459289 6.2483e-7
+ 0.000424776 -4.38319e-7
+ 0.000383111 5.96642e-7
+ 0.000354969 -4.40833e-7
+ 0.000320195 5.7525e-7
Here we can see that the second column corresponding to T1 is equal to 0 which is expected for a MESE sequence and the derivative along T2 gives the same results :
j2[:,1] ≈ vec(j)
true
Reproducibility
This page was generated with the following version of Julia:
using InteractiveUtils
io = IOBuffer();
versioninfo(io);
split(String(take!(io)), '\n')
12-element Vector{SubString{String}}:
@@ -71,10 +110,10 @@
"Commit e4ee485e909 (2023-07-05 09:39 UTC)"
"Platform Info:"
" OS: Linux (x86_64-linux-gnu)"
- " CPU: 2 × Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz"
+ " CPU: 2 × Intel(R) Xeon(R) Platinum 8272CL CPU @ 2.60GHz"
" WORD_SIZE: 64"
" LIBM: libopenlibm"
- " LLVM: libLLVM-14.0.6 (ORCJIT, icelake-server)"
+ " LLVM: libLLVM-14.0.6 (ORCJIT, skylake-avx512)"
" Threads: 1 on 2 virtual cores"
"Environment:"
" JULIA_PKG_SERVER_REGISTRY_PREFERENCE = eager"
@@ -84,4 +123,4 @@
[b6a82cc1] EPGsim v1.0.0-DEV `~/work/EPGsim.jl/EPGsim.jl`
[f6369f11] ForwardDiff v0.10.35
[98b081ad] Literate v2.14.0
- [b77e0a4c] InteractiveUtils
Settings
This document was generated with Documenter.jl version 0.27.25 on Wednesday 12 July 2023. Using Julia version 1.9.2.
+ [b77e0a4c] InteractiveUtils