I do not manage to make my fig interactive, below a simplified version of my initial script.
Any idea what is missing?
using GLMakie
x_ = 0:0.01:8π
obs_ = [Observable(0.0) for s in 1:3]
function example_func(_x, _a, _b, _c)
return _a.val .+ _b.val .* _x.^_c.val
end
y_ = example_func(x_, obs_...)
fig = Figure()
sg = SliderGrid(fig[1, 2],
(label = "a", range = 0.1:0.01:3, format = "{:.1f}", startvalue = 1),
(label = "b", range = 0:0.01:10, format = "{:.1f}", startvalue = 1),
(label = "c", range = 0:0.01:2, format = "{:0.1f}", startvalue = 1),
tellheight = false,
)
sliderobservables = [s.value for s in sg.sliders]
for (_i, _oh) in enumerate(obs_)
connect!(_oh, sliderobservables[_i])
end
ax1 = Axis(fig[1, 1], title = "Test", xlabel = "x", ylabel = "y", )
lines!(ax1, x_, y_, color = :indigo)
display(fig)
P.S.:
A nice collection of interactive plots can be found here: Examples by garrekstemo
P.P.S.:
Under Linux below Julia v1.8.3 you might face difficulties to use GLMakie:
I saw this function lift() the concept is strange to me and I wonder if there is something around like a tutorial to understand this concept better.
I do not know if this is proper coding, but it works a least:
[...]
for (_i, _oh) in enumerate(obs_)
connect!(_oh, sliderobservables[_i])
end
# --- new:
y_ = lift(sliderobservables...) do slvalues...
example_func(x_, obs_...)
end
[...]
This is how I would do it (I took the liberty of removing a lot of underscores because they were noisy to me).
using GLMakie
x = 0:0.01:8π
obs = Observable(zeros(3)) #Make the whole vector observable
#write your function as if it would not receive observables but a regular vector
function func(x, values)
return values[1] .+ values[2] .* x .^ values[3]
end
#this is where the lift will listen to changes in the observable and apply the function
y = @lift func(x, $obs)
fig = Figure()
ax1 = Axis(fig[1, 1])
lines!(ax1, x, y)
sg = SliderGrid(fig[1, 2],
(label = "a", range = 0.1:0.01:3, startvalue = 1),
(label = "b", range = 0:0.01:10, startvalue = 1),
(label = "c", range = 0:0.01:2, startvalue = 1),
tellheight = false,
)
sliderobservables = [s.value for s in sg.sliders]
#Here I connect each slider to the value inside obs and I use notify to trigger "lift" you can simplify it using map or a comprehension but I do it explicitly for clarity
on(sliderobservables[1]) do sl
obs[][1] = sl[]
notify(obs)
end
on(sliderobservables[2]) do sl
obs[][2] = sl[]
notify(obs)
end
on(sliderobservables[3]) do sl
obs[][3] = sl[]
notify(obs)
end
display(fig) #running in the REPL this line is not needed, but let's leave it for completeness