Hi, I am very new to Julia and am looking for advice/information on plotting.
I am trying to visualise my model fits for multiple instances and would like to visualise the plot and then give user input, perhaps like a 0 or 1 so that after the visualisation I can easily select the fits that I deem acceptable. Is there a standard way to do this or is there perhaps another way this kind of operation is commonly done?
Hello and welcome to the community!
What does “give some user input” mean?
Hi thank you for responding!
As with user input I was hoping it was possible to pass a boolean is some kind of way so that I can divide the plots into two groups that I want to keep and one that I do not want
Do you have something like this in mind?
plot(fits)
# manually inspect the result
acceptable_fits = [1, 2, 3, 5, 8]
plot(fits[acceptable_fits])
?
Yes something like that, where if possible I would like to loop through plotting all the fits and give a boolean which is stored and then it presents me with the next plot. so something like
order = []
for i in 1:number_fits
model = models[i]
parameters = parameter_sets[i]
fit = output(model, parameters)
plot(fit)
u = user_input()
push!(order,u)
end
I just have no idea if doing this with a user_input is at all possible.
are you looking to accept user input from the REPL in the loop there? You could do this with
help?> readline
search: readline readlines readlink
readline(io::IO=stdin; keep::Bool=false)
readline(filename::AbstractString; keep::Bool=false)
Read a single line of text from the given I/O stream or file (defaults to stdin). When reading from a file, the text is assumed to be encoded in UTF-8. Lines
in the input end with '\n' or "\r\n" or the end of an input stream. When keep is false (as it is by default), these trailing newline characters are removed
from the line before it is returned. When keep is true, they are returned as part of the line.
together with parse(Int, user_input)
or parse(Bool, user_input)
where user_input
is the string returned by readline
julia> user_input = readline()
true # I typed this
"true"
julia> parse(Bool, user_input)
true
Hi! This looks like an ideal use case for a Pluto notebook. Here is a notebook I made for a similar idea (source in this repo).
Take a look at the PlutoUI package: it facilitates using UI elements like dropdown menus, checkboxes, radio buttons, text fields, sliders, etc. (demo here). In your case, you could have a multicheckbox for your fits and collect the boolean values of all checkboxes to select what you want to plot.
It can also be fun to do something like this with a small GLMakie GUI. Here’s a mockup where the “fit” is just a line from first to last point of random data, but you get the gist. Afterwards you have your acceptance results in the accepted
Observable
and can process that further.
using GLMakie
struct Fit
y::Vector{Float64}
end
n = 100
fits = [Fit(cumsum(randn(n))) for _ in 1:n]
accepted = Observable(zeros(Bool, length(fits)))
f = Figure()
ax = Axis(f[1, 1])
i = Observable(1)
lines!(ax, @lift(fits[$i].y))
pseudofit_points = lift(i) do i
f = fits[i]
len = length(f.y)
[Point2(1, f.y[1]), Point2(len, f.y[end])]
end
lines!(ax, pseudofit_points, color = @lift($accepted[$i] ? :lightgreen : :red), linestyle = :dash, linewidth = 3)
subgl = GridLayout(f[2, 1], tellwidth = false)
prevbutton = Button(subgl[1, 1], label = "Prev")
on(prevbutton.clicks) do _
i[] = mod1(i[] - 1, n)
reset_limits!(ax)
end
Label(subgl[1, 2], @lift("Fit $($i)"))
nextbutton = Button(subgl[1, 3], label = "Next")
on(nextbutton.clicks) do _
i[] = mod1(i[] + 1, n)
reset_limits!(ax)
end
togglebutton = Button(subgl[1, 4], label = @lift($accepted[$i] ? "Reject" : "Accept"))
on(togglebutton.clicks) do _
accepted.val[i[]] =! accepted.val[i[]]
notify(accepted)
end
f
Thank you everyone for responding and giving ideas!
I ended up using the GLMakie method suggested by Jules as I was using Makie for other plotting aswell and it worked very nicely!