Skip to content

Commit dbe46bb

Browse files
louob20aris
andauthored
'Remove Section' GUI implementation (#54)
* fixed typos and some formatting in documentation * temporary solution to mac window resize bug * defined outline for delete_range function * added delete_range! to the exported functions * delte_range! basic implementation * added 'ignore selection' button to GUI * reset button resets ignored regions * bug fix * update fitted curve when removing section of f * delete_range! updates residuals * delete selection button changes * comments and docs change * docs change * removed temporary bug fix * added ker_struct to inv_out_1D type * f scales when filtering region * updated filter parameter in 1D inversion results and residuals calculation * 1D gui buttons upate * changing how residuals are calculated and plotte in 1D case * filter_selection only changes filter, changes to inv_out_1D * fit and residuals updating moved from filter_selection! to just before plotting * added more csv example files * fixed PFG plot and filtered selections case * rename filter function --------- Co-authored-by: aris <aris.mav@hotmail.com>
1 parent 373ffea commit dbe46bb

File tree

8 files changed

+111
-21
lines changed

8 files changed

+111
-21
lines changed
File renamed without changes.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
0.0007,0.346025
2+
0.0014,0.220525
3+
0.0021,0.147435
4+
0.0028,0.111799
5+
0.0035,0.0880444
6+
0.0042,0.0739969
7+
0.0049,0.0549486
8+
0.0056,0.0584712
9+
0.0063,0.0473388
10+
0.007,0.0434845
11+
0.0077,0.0281661
12+
0.0084,0.0363114
13+
0.0091,0.0402291
14+
0.0098,0.0319523
15+
0.0105,0.0415405
16+
0.0112,0.0320954
17+
0.0119,0.0252967
18+
0.0126,0.0283395
19+
0.0133,0.0177866
20+
0.014,0.0195451
21+
0.0147,0.0153591
22+
0.0154,0.0215488
23+
0.0161,0.0234149
24+
0.0168,0.0254711
25+
0.0175,0.0252673
26+
0.0182,0.0198021
27+
0.0189,0.0196933
28+
0.0196,0.0243988
29+
0.0203,0.0293147
30+
0.021,0.0200053
31+
0.0217,0.0167435
32+
0.0224,0.0238447
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
These are some IR (inversion recovery) data points corresponding to Cheshire sandstone, for testing the invert function.
1+
These are some IR (inversion recovery) data points corresponding to Cheshire sandstone, and some PFG (pulsed field gradient) data corresponding to water, for testing the invert function.
22

33
You can use them as
44

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
0.0168598,8.93818
2+
0.101159,6.9632
3+
0.185458,5.40806
4+
0.269757,4.23223
5+
0.354056,3.30936
6+
0.438355,2.59608
7+
0.522654,2.02982
8+
0.606953,1.59765
9+
0.691252,1.25206
10+
0.775551,0.986033
11+
0.85985,0.777756
12+
0.944149,0.610387
13+
1.02845,0.4785
14+
1.11275,0.37976
15+
1.19705,0.299643
16+
1.28135,0.235117

ext/gui_ext.jl

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,20 @@ function Makie.plot(res_mat::AbstractVecOrMat{NMRInversions.inv_out_1D}; selecti
102102
if res.seq in [NMRInversions.IR]
103103
ax1 = Axis(fig[1:5, 1:5], xlabel="time (s)", ylabel="Signal (a.u.)")
104104
ax2 = Axis(fig[1:5, 6:10], xlabel="T₁ (s)", xscale=log10)
105-
ax3 = Axis(fig[6:10,1:5], xlabel= "index", ylabel="Residuals (a.u.)")
105+
ax3 = Axis(fig[6:10,1:5], xlabel= "time (s)", ylabel="Residuals (a.u.)")
106106

107107
elseif res.seq in [NMRInversions.CPMG]
108108
ax1 = Axis(fig[1:5, 1:5], xlabel="time (s)", ylabel="Signal (a.u.)")
109109
ax2 = Axis(fig[1:5, 6:10], xlabel="T₂ (s)", xscale=log10)
110-
ax3 = Axis(fig[6:10,1:5], xlabel= "index", ylabel="Residuals (a.u.)")
110+
ax3 = Axis(fig[6:10,1:5], xlabel= "time (s)", ylabel="Residuals (a.u.)")
111111

112112
elseif res.seq in [NMRInversions.PFG]
113113
ax1 = Axis(fig[1:5, 1:5], xlabel="b factor (s/m² e-9)", ylabel="Signal (a.u.)")
114114
ax2 = Axis(fig[1:5, 6:10], xlabel="D (m²/s)", xscale=log10)
115-
ax3 = Axis(fig[6:10,1:5], xlabel= "index", ylabel="Residuals (a.u.)")
115+
ax3 = Axis(fig[6:10,1:5], xlabel= "b factor (s/m² e-9)", ylabel="Residuals (a.u.)")
116116
end
117117

118-
#=linkxaxes!(ax1, ax3)=#
118+
linkxaxes!(ax1, ax3)
119119

120120
for r in res_mat
121121
draw_on_axes(ax1, ax2, ax3, r, selections = selections)
@@ -157,9 +157,10 @@ function Makie.plot(res::NMRInversions.inv_out_1D)
157157
vlines!(fig.content[2], int_low, color=:red)
158158
vlines!(fig.content[2], int_high, color=:red)
159159

160-
button_label = Button(fig[8,6:10], label = "Save selection")
161-
button_reset = Button(fig[9,6:10], label = "Reset selections")
162-
button_save = Button(fig[10,6:10], label = "Save and exit")
160+
button_label = Button(fig[8,6:10], label = "Label current selection")
161+
button_filter = Button(fig[9,6:10], label = "Filter-out current selection")
162+
button_reset = Button(fig[10,6:8], label = "Reset selections")
163+
button_save = Button(fig[10,8:10], label = "Save and exit")
163164

164165
on(button_label.clicks) do _
165166
push!(res.selections, slider.interval[])
@@ -171,8 +172,19 @@ function Makie.plot(res::NMRInversions.inv_out_1D)
171172
vlines!(fig.content[2], int_high, color=:red)
172173
end
173174

175+
on(button_filter.clicks) do _
176+
empty!(fig.content[1])
177+
empty!(fig.content[2])
178+
empty!(fig.content[3])
179+
filter_range!(res, slider.interval[])
180+
draw_on_axes(fig.content[1], fig.content[2], fig.content[3], res, selections = true)
181+
vlines!(fig.content[2], int_low, color=:red)
182+
vlines!(fig.content[2], int_high, color=:red)
183+
end
184+
174185
on(button_reset.clicks) do _
175186
empty!(res.selections)
187+
res.filter = ones(length(res.X))
176188
empty!(fig.content[1])
177189
empty!(fig.content[2])
178190
empty!(fig.content[3])
@@ -187,18 +199,26 @@ function Makie.plot(res::NMRInversions.inv_out_1D)
187199
save(savedir, f)
188200
end
189201

202+
190203
return fig
191204
end
192205

193206

194207
function draw_on_axes(ax1, ax2, ax3, res::NMRInversions.inv_out_1D; selections = false)
195208

196-
c = length(ax2.scene.plots)
209+
# apply filter to f and update fitted curve and residuals
210+
f_prime = res.filter .* res.f
211+
yfit_prime = create_kernel(
212+
res.seq, res.xfit, (res.seq == PFG ? res.X .* 1e9 : res.X)) * f_prime
213+
r_prime = create_kernel(
214+
res.seq, res.x, (res.seq == PFG ? res.X .* 1e9 : res.X)) * f_prime - res.y
197215

216+
c = length(ax2.scene.plots)
198217
scatter!(ax1, res.x, real.(res.y), colormap=:tab10, colorrange=(1, 10), color=c)
199-
lines!(ax1, res.xfit, res.yfit, colormap=:tab10, colorrange=(1, 10), color=c)
200-
lines!(ax2, res.X, res.f, colormap=:tab10, colorrange=(1, 10), color=c)
201-
lines!(ax3, res.r, colormap=:tab10, colorrange=(1, 10), color=c)
218+
lines!(ax1, res.xfit, yfit_prime, colormap=:tab10, colorrange=(1, 10), color=c)
219+
lines!(ax2, res.X, f_prime, colormap=:tab10, colorrange=(1, 10), color=c)
220+
lines!(ax3, res.x, r_prime, colormap=:tab10, colorrange=(1, 10), color=c)
221+
scatter!(ax3, res.x, r_prime, colormap=:tab10, colorrange=(1, 10), color=c)
202222

203223

204224
if selections
@@ -230,11 +250,11 @@ function draw_on_axes(ax1, ax2, ax3, res::NMRInversions.inv_out_1D; selections =
230250
ax2,
231251
res.X[s[1]:s[2]],
232252
zeros(length(res.f[s[1]:s[2]])),
233-
res.f[s[1]:s[2]],
253+
(res.f .* res.filter)[s[1]:s[2]],
234254
color = clr, alpha = 0.5
235255
)
236256

237-
height = (1 - (i-1) * 0.1) * maximum(res.f)
257+
height = (1 - (i-1) * 0.1) * maximum(res.f .* res.filter)
238258
text!(
239259
ax2, res.X[2], height,
240260
text = Xlabel[1]*"$(round(wa[i], sigdigits = 2))"*Xlabel[2],
@@ -622,8 +642,11 @@ function Makie.plot(res::NMRInversions.inv_out_2D)
622642
end
623643

624644
end ## BUTTON CLICKS
625-
645+
646+
626647
gui
648+
649+
627650
end
628651

629652
end

src/inversion_functions.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,26 @@ function invert(seq::Type{<:pulse_sequence1D}, x::AbstractArray, y::Vector;
5959
if isa(alpha, Real)
6060

6161
α = alpha
62-
f, r = solve_regularization(ker_struct.K, ker_struct.g, α, solver)
62+
f, _ = solve_regularization(ker_struct.K, ker_struct.g, α, solver)
6363

6464
else
6565

66-
f, r, α = find_alpha(ker_struct, solver, alpha)
66+
f, _, α = find_alpha(ker_struct, solver, alpha)
6767

6868
end
6969

7070
x_fit = exp10.(range(log10(1e-8), log10(1.1 * x[end]), 512))
7171
y_fit = create_kernel(seq, x_fit, X) * f
7272

7373
isreal(y) ? SNR = NaN : SNR = calc_snr(y)
74+
75+
r = create_kernel(seq, x, X) * f - y
7476

7577
if seq == PFG
7678
X .= X ./ 1e9
7779
end
7880

79-
80-
return inv_out_1D(seq, x, y, x_fit, y_fit, X, f, r, SNR, α, [],"")
81+
return inv_out_1D(seq, x, y, x_fit, y_fit, X, f, r, SNR, α, [], ones(length(X)),"")
8182

8283
end
8384

src/misc.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,19 @@ function weighted_averages(r::inv_out_2D)
247247

248248
return wa_T1, wa_T2
249249
end
250+
251+
252+
export filter_range!
253+
"""
254+
filter_range!(res::inv_res_1D , range)
255+
Apply selected range to the filter, scaling it to keep the integral of `f` constant.
256+
"""
257+
function filter_range!(res::inv_out_1D, range)
258+
259+
integral = sum(res.f)
260+
res.filter[range[1]:range[2]] .= 0
261+
new_integral = sum(res.f .* res.filter)
262+
scale = new_integral != 0 ? integral / new_integral : 0
263+
res.filter .= res.filter .* scale
264+
265+
end

src/types.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ end
341341

342342
export inv_out_1D
343343
"""
344-
inv_out_1D(seq, x, y, xfit, yfit, X, f, r, SNR, α, selections, title)
344+
inv_out_1D(seq, x, y, xfit, yfit, X, f, r, SNR, α, selections, filter, title)
345345
346346
Output of the invert function for 1D pulse sequences.
347347
A structure containing the following fields:
@@ -355,7 +355,8 @@ A structure containing the following fields:
355355
- `r`, the residuals.
356356
- `SNR`, the signal-to-noise ratio.
357357
- `α`, the regularization parameter.
358-
- `selections`, a vector of tuples whose elements are indicate the first and last index of the selected peaks.
358+
- `selections`, a vector of tuples whose elements indicate the first and last index of the selected peaks.
359+
- `filter`, a vector representing the mask used to filter and scale the data.
359360
- `title`, a title describing the data.
360361
361362
"""
@@ -371,6 +372,7 @@ mutable struct inv_out_1D
371372
SNR::Real
372373
alpha::Real
373374
selections::Vector{Tuple}
375+
filter::Vector
374376
title::String
375377
end
376378

0 commit comments

Comments
 (0)