Add Jaguar button | parameter updates working but not reflected in GLMakie yet
parent
f4c94c7ace
commit
a001c03104
|
|
@ -17,9 +17,9 @@ F, k = Observable(0.060), Observable(0.062)
|
||||||
params_obs = Observable(GSParams(N, dx, Du[], Dv[], F[], k[]))
|
params_obs = Observable(GSParams(N, dx, Du[], Dv[], F[], k[]))
|
||||||
lift(Du, Dv, F, k) do u, v, f, ki
|
lift(Du, Dv, F, k) do u, v, f, ki
|
||||||
params_obs[] = GSParams(N, dx, u, v, f, ki)
|
params_obs[] = GSParams(N, dx, u, v, f, ki)
|
||||||
|
println("lifted")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
U = ones(N, N)
|
U = ones(N, N)
|
||||||
V = zeros(N, N)
|
V = zeros(N, N)
|
||||||
heat_obs = Observable(U)
|
heat_obs = Observable(U)
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
module Visualization
|
module Visualization
|
||||||
include("gray_scott_solver.jl")
|
include("gray_scott_solver.jl")
|
||||||
using GLMakie, Observables, Makie
|
using GLMakie, Observables, Makie
|
||||||
|
using Random
|
||||||
using .GrayScottSolver
|
using .GrayScottSolver
|
||||||
|
|
||||||
"""
|
"""
|
||||||
step_through_solution(sol::SolutionType, N::Int)
|
step_through_solution(sol::SolutionType, N::Int)
|
||||||
|
|
||||||
Function for visualization for the output of run_simulation
|
Function for visualization for the output of run_simulation
|
||||||
|
|
||||||
# Arguments
|
# Arguments
|
||||||
- `sol`: computed differential equation by run_simulation
|
- sol: computed differential equation by run_simulation
|
||||||
- `N`: size of the N×N grid
|
- N: size of the N×N grid
|
||||||
|
|
||||||
# Returns
|
# Returns
|
||||||
- ``: Displays created figure
|
- Displays created figure
|
||||||
"""
|
"""
|
||||||
function step_through_solution(sol, N::Int)
|
function step_through_solution(sol, N::Int)
|
||||||
fig = Figure(resolution=(600, 600))
|
fig = Figure(resolution=(600, 600))
|
||||||
|
|
@ -24,37 +26,67 @@ function step_through_solution(sol, N::Int)
|
||||||
# Initialize heatmap with first time step
|
# Initialize heatmap with first time step
|
||||||
u0 = reshape(sol[1][1:N^2], N, N)
|
u0 = reshape(sol[1][1:N^2], N, N)
|
||||||
heat_obs = Observable(u0)
|
heat_obs = Observable(u0)
|
||||||
hmap = heatmap!(ax, heat_obs, colormap=:magma)
|
heatmap!(ax, heat_obs, colormap=:magma)
|
||||||
|
|
||||||
on(textbox.stored_string) do s
|
on(textbox.stored_string) do s
|
||||||
F[] = parse(Float64, s)
|
F[] = parse(Float64, s)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Update heatmap on slider movement
|
# Update heatmap on slider movement
|
||||||
on(slider.value) do i
|
on(slider.value) do i
|
||||||
u = reshape(sol[i][1:N^2], N, N)
|
u = reshape(sol[i][1:N^2], N, N)
|
||||||
heat_obs[] = u
|
heat_obs[] = u
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
display(fig)
|
display(fig)
|
||||||
end
|
end
|
||||||
|
|
||||||
function coord_to_index(x, y, N)
|
function coord_to_index(x, y, N)
|
||||||
ix = clamp(round(Int, x), 1, N)
|
ix = clamp(round(Int, x), 1, N)
|
||||||
iy = clamp(round(Int, y), 1, N)
|
iy = clamp(round(Int, y), 1, N)
|
||||||
return ix, iy
|
return ix, iy
|
||||||
end
|
end
|
||||||
|
|
||||||
function reset!(U, V, heat_obs)
|
function reset!(U, V, heat_obs)
|
||||||
U .= 1.0
|
U .= 1.0
|
||||||
V .= 0.0
|
V .= 0.0
|
||||||
|
# Default starting point for Run
|
||||||
|
default_start!(U, V)
|
||||||
|
heat_obs[] = copy(U)
|
||||||
|
end
|
||||||
|
|
||||||
|
function default_start!(U, V)
|
||||||
center = size(U, 1) ÷ 2
|
center = size(U, 1) ÷ 2
|
||||||
radius = 10
|
radius = 10
|
||||||
U[center-radius:center+radius, center-radius:center+radius] .= 0.50
|
U[center-radius:center+radius, center-radius:center+radius] .= 0.50
|
||||||
V[center-radius:center+radius, center-radius:center+radius] .= 0.25
|
V[center-radius:center+radius, center-radius:center+radius] .= 0.25
|
||||||
heat_obs[] = copy(U)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function starting_points!(U, V)
|
||||||
|
N = size(U, 1)
|
||||||
|
radius = 10
|
||||||
|
jitter = 5
|
||||||
|
margin = radius + 2
|
||||||
|
rels = [
|
||||||
|
(1/4, 1/4), (3/4, 1/4), (1/2, 1/2),
|
||||||
|
(1/4, 3/4), (3/4, 3/4), (1/2, 1/8)
|
||||||
|
]
|
||||||
|
for (px, py) in rels
|
||||||
|
cx = clamp(round(Int, px * N) + rand(-jitter:jitter), margin, N - margin)
|
||||||
|
cy = clamp(round(Int, py * N) + rand(-jitter:jitter), margin, N - margin)
|
||||||
|
for x in (cx - radius):(cx + radius), y in (cy - radius):(cy + radius)
|
||||||
|
if 1 ≤ x ≤ N && 1 ≤ y ≤ N && hypot(x - cx, y - cy) ≤ radius
|
||||||
|
U[x, y] = 0.50
|
||||||
|
V[x, y] = 0.25
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function param_box!(grid, row, labeltxt, observable::Observable)
|
function param_box!(grid, row, labeltxt, observable::Observable)
|
||||||
Label(grid[row, 1], labeltxt)
|
Label(grid[row, 1], labeltxt)
|
||||||
box = Textbox(grid[row, 2], validator=Float64, width=50, placeholder=labeltxt, stored_string="$(observable[])")
|
box = Textbox(grid[row, 2], validator=Float64, width=50,
|
||||||
|
placeholder=labeltxt, stored_string="$(observable[])")
|
||||||
on(box.stored_string) do s
|
on(box.stored_string) do s
|
||||||
try
|
try
|
||||||
observable[] = parse(Float64, s)
|
observable[] = parse(Float64, s)
|
||||||
|
|
@ -70,69 +102,86 @@ function build_ui(U, V, Du, Dv, F, k, params_obs, heat_obs)
|
||||||
fig = Figure(size=(800, 800))
|
fig = Figure(size=(800, 800))
|
||||||
gh = GridLayout(fig[1, 1])
|
gh = GridLayout(fig[1, 1])
|
||||||
ax = Axis(gh[1, 1])
|
ax = Axis(gh[1, 1])
|
||||||
hm = Makie.heatmap!(ax, heat_obs, colormap=:viridis)
|
heatmap!(ax, heat_obs, colormap=:viridis)
|
||||||
deactivate_interaction!(ax, :rectanglezoom)
|
deactivate_interaction!(ax, :rectanglezoom)
|
||||||
ax.aspect = DataAspect()
|
ax.aspect = DataAspect()
|
||||||
|
|
||||||
run_label = Observable{String}("Run")
|
run_label = Observable("Run")
|
||||||
stepsize = Observable(30)
|
stepsize = Observable(30)
|
||||||
# # Controls
|
|
||||||
|
# Controls
|
||||||
fig[2, 1] = buttongrid = GridLayout(ax.scene, tellwidth=false)
|
fig[2, 1] = buttongrid = GridLayout(ax.scene, tellwidth=false)
|
||||||
btn_step = Button(buttongrid[1, 1], width=50, label="Step")
|
btn_step = Button(buttongrid[1, 1], width=60, label="Step")
|
||||||
btn_start = Button(buttongrid[1, 2], width=50, label=run_label)
|
btn_start = Button(buttongrid[1, 2], width=60, label=run_label)
|
||||||
btn_reset = Button(buttongrid[1, 3], width=50, label="Reset")
|
btn_reset = Button(buttongrid[1, 3], width=60, label="Reset")
|
||||||
slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:100, format="{}x", width=350, startvalue=stepsize[]))
|
btn_Jaguar = Button(buttongrid[1, 4], width=60, label="Jaguar")
|
||||||
|
|
||||||
|
slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:100,
|
||||||
|
format="{}x", width=350,
|
||||||
|
startvalue=stepsize[]))
|
||||||
speed_slider = slidergrid.sliders[1].value
|
speed_slider = slidergrid.sliders[1].value
|
||||||
|
|
||||||
|
|
||||||
gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
|
gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
|
||||||
rowsize!(gh, 1, Relative(1.0))
|
rowsize!(gh, 1, Relative(1.0))
|
||||||
|
|
||||||
|
|
||||||
param_box!(textboxgrid, 1, "Du", Du)
|
param_box!(textboxgrid, 1, "Du", Du)
|
||||||
param_box!(textboxgrid, 2, "Dv", Dv)
|
param_box!(textboxgrid, 2, "Dv", Dv)
|
||||||
param_box!(textboxgrid, 3, "Feed", F)
|
param_box!(textboxgrid, 3, "Feed", F)
|
||||||
param_box!(textboxgrid, 4, "kill", k)
|
param_box!(textboxgrid, 4, "kill", k)
|
||||||
|
|
||||||
# Timer and state for animation
|
println("aufruf")
|
||||||
running = Observable(false)
|
|
||||||
|
|
||||||
|
running = Observable(false)
|
||||||
on(running) do r
|
on(running) do r
|
||||||
run_label[] = r ? "Pause" : "Run"
|
run_label[] = r ? "Pause" : "Run"
|
||||||
end
|
end
|
||||||
|
|
||||||
on(speed_slider) do s
|
on(speed_slider) do s
|
||||||
try
|
stepsize[] = s
|
||||||
stepsize[] = s
|
println("Changed stepsize to $s")
|
||||||
println("Changed stepsize to $s")
|
|
||||||
catch
|
|
||||||
@warn "Invalid input for $s"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
# Button Listeners
|
|
||||||
on(btn_step.clicks) do _
|
on(btn_step.clicks) do _
|
||||||
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
||||||
end
|
end
|
||||||
|
|
||||||
on(btn_start.clicks) do _
|
on(btn_start.clicks) do _
|
||||||
running[] = !running[]
|
running[] = !running[]
|
||||||
|
if running[]
|
||||||
|
reset!(U, V, heat_obs)
|
||||||
|
@async while running[]
|
||||||
|
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
||||||
|
sleep(0.0015)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
on(btn_start.clicks) do _
|
on(btn_Jaguar.clicks) do _
|
||||||
@async while running[]
|
|
||||||
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
Du[] = 0.142
|
||||||
sleep(0.0015) # ~20 FPS
|
Dv[] = 0.078
|
||||||
|
F[] = 0.0617
|
||||||
|
k[] = 0.062
|
||||||
|
|
||||||
|
if !running[]
|
||||||
|
running[] = true
|
||||||
|
U .= 1.0; V .= 0.0
|
||||||
|
@async while running[]
|
||||||
|
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
||||||
|
sleep(0.0015)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
starting_points!(U, V)
|
||||||
|
heat_obs[] = copy(U)
|
||||||
end
|
end
|
||||||
|
|
||||||
on(btn_reset.clicks) do _
|
on(btn_reset.clicks) do _
|
||||||
running[] = false
|
running[] = false
|
||||||
reset!(U, V, heat_obs)
|
reset!(U, V, heat_obs)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return fig
|
return fig
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
export step_through_solution, build_ui
|
export step_through_solution, build_ui
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue