# Interactive FFT with an intervalslider in Makie

Hello, I have taken a relatively large amount of readings over time and would now like to look at them in detail. For this purpose I use an interval slider in Makie with which I can zoom into my data. This works already very well.
In the next step I want to run a fast fourier transformation dynamically over the selected area. This should be adjusted with the slider position. I’ve played around a bit, but haven’t made it to work yet. Maybe someone of you has an idea.

``````intSh1 = IntervalSlider(fig[2, 1], range = collect(1:1:length(test_time)), startvalues = (1, length(test_time)), linewidth = 20)

Label(fig[2, 1], @lift(string(test_time[\$(intSh1.interval)[1]]) * " sec bis " * string(test_time[\$(intSh1.interval)[2]]) * " sec"), tellwidth = false)

vlines!(ax0, @lift(test_time[\$(intSh1.interval)[1]]), ymin = -2.0, ymax = 2.0, color = :red, linewidth = 2)
vlines!(ax0, @lift(test_time[\$(intSh1.interval)[2]]), ymin = -2.0, ymax = 2.0, color = :red, linewidth = 2)

F = rfft(volt) |> fftshift
freqs = rfftfreq(length(test_time), 1/(steptime*1e-3)) |> fftshift

new_fft = lift(intSh1.interval) do val
F = rfft(volt[val[1]:val[2]]) |> fftshift
freqs = rfftfreq(length(test_time[val[1]:val[2]]), 1/(steptime*1e-3)) |> fftshift
end

new_lims = lift(intSh1.interval) do val
limits!(ax1, FRect(test_time[val[1]], -0.75, test_time[val[2]] - test_time[val[1]], 1.5))
end

lines!(ax0, test_time, volt, linewidth = 0.5, color = :blue)
lines!(ax1, test_time, volt, linewidth = 1, color = :blue)
lines!(ax2, freqs, abs.(F), linewidth = 1, color = :blue)

display(fig)

``````

1 Like
``````using FFTW, GLMakie

function interactive(data, timestep)

N = size(data, 1)

time = range(0, step=timestep, length=N) |> collect

fig = Figure(resolution=(2400, 1400))

ax0 = fig[1,1] = Axis(fig)

intSh1 = fig[2,1] = IntervalSlider(
fig,
range = 1:N,
startvalues = (1, N),
linewidth = 20)
fig[2, 1] = Label(
fig,
@lift(string(time[\$(intSh1.interval)[1]]) * " sec bis " * string(time[\$(intSh1.interval)[2]]) * " sec"),
tellwidth = false)

ax1 = fig[3,1] = Axis(fig)
ax2 = fig[4,1] = Axis(fig)

vlines!(ax0, @lift(time[\$(intSh1.interval)[1]]), ymin = -2.0, ymax = 2.0, color = :red, linewidth = 2)
vlines!(ax0, @lift(time[\$(intSh1.interval)[2]]), ymin = -2.0, ymax = 2.0, color = :red, linewidth = 2)

# The plotted values need to be observables so they update on change, and they must
# be synchronized.
new_freqs = Node(rfftfreq(N, 1/timestep)|>fftshift|>collect)
new_F = lift(intSh1.interval) do val
new_freqs.val = rfftfreq(val[2]-val[1]+1, 1/timestep) |> fftshift |> collect
rfft(data[val[1]:val[2]]) |> fftshift .|> abs
end

new_lims = lift(intSh1.interval) do val
limits!(ax1, FRect(time[val[1]], -0.75, time[val[2]] - time[val[1]], 1.5))
end

lines!(ax0, time, data, linewidth = 0.5, color = :blue)
lines!(ax1, time, data, linewidth = 1, color = :blue)
lines!(ax2, new_freqs, new_F, linewidth = 1, color = :blue)

display(fig)

end
``````
1 Like

Thank you for the quick reply. Unfortunately I still do not understand the functions of `|>`
There is a function applied to the argument before it or? What is the advantage in this syntax? If I have understood it correctly are `sum([1:5;])` and `[1:5;] |> sum` the same or?

Thanks and sorry if it’s a very stupid question

Yes, it’s just a stylistic question. Sometimes a sequence of functions being applied is easier to grasp than reading inside out `func3(func2(func1(x)))`