Interactive FFT with an intervalslider in Makie

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.
    # https://makie.juliaplots.org/stable/interaction/nodes.html#Problems-With-Synchronous-Updates
    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