Skip to content

Commit 201fdf9

Browse files
author
arismav
committed
WIP
1 parent 9f02139 commit 201fdf9

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

src/NMRInversions.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using Optim
99

1010
include("types.jl")
1111
include("brd.jl")
12+
include("sge.jl")
1213
include("coordinate_descent.jl")
1314
include("optim_least_squares.jl")
1415
include("pdhgm.jl")

src/sge.jl

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
using Optim
2+
3+
"""
4+
sigmoid
5+
Return an ascending sigmoid function of the same size as X.
6+
7+
Arguments:
8+
- `X` is the x-axis of the data.
9+
- `X_c` the value at which the sigmoid will be 0.
10+
11+
Keyword (optional) arguments:
12+
- `width` determines the steepness of the sigmoid.
13+
- `scale` function describing the scale of the input
14+
vector `X`. Defaults to `log10`, and `identity` can be
15+
used for a linear scale.
16+
17+
Some indicative values:
18+
- `width=1`: almost like a line with slope `1`.
19+
- `width=0.05`: looks like a typical sigmoid.
20+
- `width=0.001`: makes it basically a step function.
21+
"""
22+
function sigmoid(X::AbstractVector, X_c::Real;
23+
width::Real=0.05, scale::Function=log10)
24+
25+
scaled_X = scale.(X)
26+
sigcent = scaled_X .- scale(X_c)
27+
28+
range_X = maximum(scaled_X) - minimum(scaled_X)
29+
effective_width = width * range_X
30+
31+
return 1 ./ (1 .+ exp.(-sigcent ./ effective_width))
32+
33+
end
34+
35+
36+
"""
37+
sge
38+
Simultaneous Gaussian-Exponential inversion solver.
39+
"""
40+
struct sge <: regularization_solver
41+
s_centre::Real
42+
s_width::Real
43+
s_weight::Real
44+
end
45+
46+
47+
function solve_regularization(K::AbstractMatrix, g::AbstractVector, α::Real, solver::sge)
48+
49+
s = sigmoid(X, solver.s_centre , width = solver.s_width)
50+
51+
solver = optim_nnls(L = Diagonal([s ; 1 .- s]))
52+
f, r = solve_regularization(K_sge, g, α, solver)
53+
54+
end
55+
56+
57+
# Testing the paper method, for reference
58+
function SGE_washburn(X, M, to, T2;
59+
smoothing = 0.0001,
60+
sig = 38,
61+
sigwidth = 1.0,
62+
sigweightA = 0.001,
63+
sigweightB = 0.001,
64+
)
65+
66+
halfX = div(length(X), 2)
67+
A = X[1:halfX]
68+
B = X[(halfX + 1):end]
69+
70+
T = eltype(X)
71+
72+
Mhat = zeros(T, length(M))
73+
74+
sigcent = collect(T, (-sig):(-sig + halfX - 1))
75+
76+
sigup = ((1 ./ (1 .+ exp.(-sigcent .* sigwidth))) .* sigweightA) .+ smoothing
77+
sigdown = (smoothing .+ (1 .- (1 ./ (1 .+ exp.(-sigcent .* sigwidth)))) .* sigweightB)
78+
79+
for ii in 1:halfX
80+
Mhat .+= A[ii] .* exp.(-((to ./ T2[ii]) .^ 2)) .+ B[ii] .* exp.(-to ./ T2[ii])
81+
end
82+
83+
SS = sum((M .- Mhat) .^ 2) + sum(A .* sigup) + sum(B .* sigdown)
84+
85+
return SS
86+
end
87+
88+
function log_gaussian(x, μ, σ, amp)
89+
return amp .* exp.(-(log10.(x) .- log10(μ)).^2 ./ (2 * σ^2))
90+
end
91+
92+
function test_sge()
93+
94+
# make T distributions
95+
X = collect(logrange(1e-5, 1, 50))
96+
f_gauss = log_gaussian(X, 0.2e-3, 0.2, 0.6)
97+
f_exp = log_gaussian(X, 0.6e-1, 0.2, 0.4)
98+
99+
x = collect(range(1e-5,1e-2,500))
100+
101+
K_g = create_kernel(CPMG, x, X, gaussian = true)
102+
K_e = create_kernel(CPMG, x, X)
103+
104+
y_gaussian = K_g * f_gauss
105+
y_exp = K_e * f_exp
106+
107+
y = y_gaussian + y_exp
108+
109+
s = sigmoid(X, 5e-3 , width = 0.001)
110+
111+
# return X, f_gauss + f_exp
112+
113+
K_sge = [K_g K_e]
114+
115+
s_weight = 1
116+
117+
solver = optim_nnls(L = Diagonal(s_weight .* [s ; 1 .- s]), opts= Optim.Options(show_trace=true))
118+
119+
f, r = solve_regularization(K_sge, y, 1.0, solver)
120+
121+
return f
122+
123+
# initial_guess = fill(1.0 / (length(X) * 2), length(X) * 2)
124+
# lower_bounds = fill(0.0, length(initial_guess))
125+
# upper_bounds = fill(200.0, length(initial_guess))
126+
#
127+
# inner_obj = X -> NMRInversions.SGE_washburn(X, y, x, X)
128+
#
129+
# res = optimize(
130+
# inner_obj,
131+
# lower_bounds,
132+
# upper_bounds,
133+
# initial_guess,
134+
# Fminbox(LBFGS()),
135+
# Optim.Options(
136+
# show_trace = true,
137+
# outer_iterations = 5,
138+
# iterations = 100,
139+
# f_abstol = 1e-3,
140+
# f_reltol = 1e-3,
141+
# g_tol = 1e-4
142+
# ),
143+
# autodiff = :forward
144+
# )
145+
#
146+
# optimized_X = Optim.minimizer(res)
147+
# A_final = optimized_X[1:length(X)]
148+
# B_final = optimized_X[length(X)+1:end]
149+
#
150+
# return x, y, X, f_gauss, f_exp, A_final, B_final
151+
#
152+
end
153+
154+
#==
155+
function testplot(x, y, T2Values, f_gauss, f_exp, A_final, B_final)
156+
fig = GLMakie.Figure()
157+
ax_1 = GLMakie.Axis(fig[1,:], xscale = log10, title="Distribution")
158+
ax_2 = GLMakie.Axis(fig[2,:], title = "CPMG")
159+
ax_3 = GLMakie.Axis(fig[3,:], xscale = log10, title="Results")
160+
lines!(ax_1, T2Values, f_gauss)
161+
lines!(ax_1, T2Values, f_exp)
162+
lines!(ax_2, x, y)
163+
lines!(ax_3, T2Values, A_final)
164+
lines!(ax_3, T2Values, B_final)
165+
return fig
166+
end
167+
==#

0 commit comments

Comments
 (0)