Merge pull request 'Switch zwischen FHN und GrayScott einbauen' (#5) from feat/common_ui into main
Reviewed-on: #5main
commit
efed0a47e0
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
julia_version = "1.11.5"
|
julia_version = "1.11.5"
|
||||||
manifest_format = "2.0"
|
manifest_format = "2.0"
|
||||||
project_hash = "5fd84347cd356de5b819aa3ea793fa63c45180e4"
|
project_hash = "b5f5f0b50b1e0b7dd05bb93e0b1bb03fea235d53"
|
||||||
|
|
||||||
[[deps.ADTypes]]
|
[[deps.ADTypes]]
|
||||||
git-tree-sha1 = "e2478490447631aedba0823d4d7a80b2cc8cdb32"
|
git-tree-sha1 = "e2478490447631aedba0823d4d7a80b2cc8cdb32"
|
||||||
|
|
@ -635,9 +635,9 @@ uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
|
|
||||||
[[deps.EnzymeCore]]
|
[[deps.EnzymeCore]]
|
||||||
git-tree-sha1 = "7d7822a643c33bbff4eab9c87ca8459d7c688db0"
|
git-tree-sha1 = "8272a687bca7b5c601c0c24fc0c71bff10aafdfd"
|
||||||
uuid = "f151be2c-9106-41f4-ab19-57ee4f262869"
|
uuid = "f151be2c-9106-41f4-ab19-57ee4f262869"
|
||||||
version = "0.8.11"
|
version = "0.8.12"
|
||||||
weakdeps = ["Adapt"]
|
weakdeps = ["Adapt"]
|
||||||
|
|
||||||
[deps.EnzymeCore.extensions]
|
[deps.EnzymeCore.extensions]
|
||||||
|
|
@ -1419,9 +1419,9 @@ version = "1.11.0"
|
||||||
|
|
||||||
[[deps.MathTeXEngine]]
|
[[deps.MathTeXEngine]]
|
||||||
deps = ["AbstractTrees", "Automa", "DataStructures", "FreeTypeAbstraction", "GeometryBasics", "LaTeXStrings", "REPL", "RelocatableFolders", "UnicodeFun"]
|
deps = ["AbstractTrees", "Automa", "DataStructures", "FreeTypeAbstraction", "GeometryBasics", "LaTeXStrings", "REPL", "RelocatableFolders", "UnicodeFun"]
|
||||||
git-tree-sha1 = "31a99cb7537f812e1d6be893a71804c35979f1be"
|
git-tree-sha1 = "6e64d2321257cc52f47e193407d0659ea1b2b431"
|
||||||
uuid = "0a4f8689-d25c-4efe-a92b-7142dfc1aa53"
|
uuid = "0a4f8689-d25c-4efe-a92b-7142dfc1aa53"
|
||||||
version = "0.6.4"
|
version = "0.6.5"
|
||||||
|
|
||||||
[[deps.MatrixFactorizations]]
|
[[deps.MatrixFactorizations]]
|
||||||
deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"]
|
deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"]
|
||||||
|
|
@ -2784,9 +2784,9 @@ version = "2.0.3+0"
|
||||||
|
|
||||||
[[deps.libpng_jll]]
|
[[deps.libpng_jll]]
|
||||||
deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"]
|
deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"]
|
||||||
git-tree-sha1 = "002748401f7b520273e2b506f61cab95d4701ccf"
|
git-tree-sha1 = "cd155272a3738da6db765745b89e466fa64d0830"
|
||||||
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
|
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
|
||||||
version = "1.6.48+0"
|
version = "1.6.49+0"
|
||||||
|
|
||||||
[[deps.libsixel_jll]]
|
[[deps.libsixel_jll]]
|
||||||
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "libpng_jll"]
|
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "libpng_jll"]
|
||||||
|
|
|
||||||
|
|
@ -1,58 +1,34 @@
|
||||||
include("../src/utils/constants.jl")
|
|
||||||
#include("../src/fhn_solver.jl")
|
|
||||||
include("../src/gray_scott_solver.jl")
|
|
||||||
include("../src/visualization.jl")
|
include("../src/visualization.jl")
|
||||||
|
|
||||||
using Observables
|
using Observables
|
||||||
using GLMakie
|
using GLMakie
|
||||||
|
|
||||||
using .Constants
|
using .Visualization.Constants
|
||||||
using .Visualization
|
using .Visualization
|
||||||
|
|
||||||
# GSParams
|
# GSParams AND FHNParams
|
||||||
N = 128
|
N = 128
|
||||||
dx = 1.0
|
dx = 1.0
|
||||||
Du, Dv = Observable(0.16), Observable(0.08)
|
params = (
|
||||||
F, k = Observable(0.060), Observable(0.062)
|
N=Observable(128),
|
||||||
|
dx=Observable(1.0),
|
||||||
param_observables = (
|
Du=Observable(0.16),
|
||||||
Du=Du,
|
Dv=Observable(0.08),
|
||||||
Dv=Dv,
|
F=Observable(0.060),
|
||||||
F=F,
|
k=Observable(0.062),
|
||||||
k=k,
|
ϵ=Observable(0.05),
|
||||||
|
a=Observable(0.7),
|
||||||
|
b=Observable(0.8)
|
||||||
)
|
)
|
||||||
|
|
||||||
"""
|
params_obs = Observable{Constants.CombinedPDEParams}(CombinedPDEParams(N, dx, params.Du[], params.Dv[], params.F[], params.k[], params.ϵ[], params.a[], params.b[]))
|
||||||
# FHNParams
|
lift(params.N, params.dx, params.Du, params.Dv, params.F, params.k, params.ϵ, params.a, params.b) do N, dx, Du, Dv, F, k, ϵ, a, b
|
||||||
N = 128
|
params_obs[] = CombinedPDEParams(N, dx, Du, Dv, F, k, ϵ, a, b)
|
||||||
dx = 1.0
|
|
||||||
Du, Dv = Observable(0.016), Observable(0.1)
|
|
||||||
ϵ, a, b = Observable(0.1), Observable(0.5), Observable(0.9)
|
|
||||||
param_observables = (
|
|
||||||
Du=Du,
|
|
||||||
Dv=Dv,
|
|
||||||
ϵ=ϵ,
|
|
||||||
a=a,
|
|
||||||
b=b
|
|
||||||
)
|
|
||||||
"""
|
|
||||||
params_obs = Observable(Constants.GSParams(N, dx, Du[], Dv[], F[], k[]))
|
|
||||||
#params_obs = Observable(FHNParams(N=N, dx=dx, Du=Du[], Dv=Dv[], ϵ=ϵ[], a=a[], b=b[]))
|
|
||||||
|
|
||||||
|
|
||||||
lift(Du, Dv, F, k) do u, v, f, ki
|
|
||||||
params_obs[] = GSParams(N, dx, u, v, f, ki)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
|
||||||
lift(Du, Dv, ϵ, a, b) do d_u, d_v, eps, aa, bb
|
|
||||||
params_obs[] = FHNParams(N=N, dx=dx, Du=d_u, Dv=d_v, ϵ=eps, a=aa, b=bb)
|
|
||||||
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)
|
||||||
|
|
||||||
fig = build_ui(U, V, param_observables, params_obs, heat_obs)
|
fig = build_ui(U, V, params, params_obs, heat_obs)
|
||||||
display(fig)
|
display(fig)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
module FHNSolver
|
||||||
|
|
||||||
include("utils/laplacian.jl")
|
include("utils/laplacian.jl")
|
||||||
|
|
||||||
using DifferentialEquations
|
using DifferentialEquations
|
||||||
|
|
@ -45,7 +47,8 @@ function fhn!(du, u, p::FHNParams, t)
|
||||||
du .= vcat(vec(fu_full), vec(fv_full))
|
du .= vcat(vec(fu_full), vec(fv_full))
|
||||||
end
|
end
|
||||||
|
|
||||||
function step!(U, V, params_obs::Observable; dx=1)
|
function step_fhn!(U, V, params_obs::Observable; dx=1)
|
||||||
|
"""
|
||||||
p = params_obs[]
|
p = params_obs[]
|
||||||
|
|
||||||
# Flatten initial condition (activation u, recovery v)
|
# Flatten initial condition (activation u, recovery v)
|
||||||
|
|
@ -65,11 +68,24 @@ function step!(U, V, params_obs::Observable; dx=1)
|
||||||
U .= u_new
|
U .= u_new
|
||||||
V .= v_new
|
V .= v_new
|
||||||
|
|
||||||
|
return U
|
||||||
|
"""
|
||||||
|
|
||||||
|
params = params_obs[]
|
||||||
|
|
||||||
|
Δu = laplacian(U, params.dx)
|
||||||
|
Δv = laplacian(V, params.dx)
|
||||||
|
|
||||||
|
u = U[2:end-1, 2:end-1]
|
||||||
|
v = V[2:end-1, 2:end-1]
|
||||||
|
|
||||||
|
fu = params.Du .* Δu .+ u .- (u .^ 3) ./ 3 .- v
|
||||||
|
fv = params.Dv .* Δv .+ params.ϵ .* (u .+ params.a .- params.b .* v)
|
||||||
|
|
||||||
|
U[2:end-1, 2:end-1] .+= 0.1 .* fu
|
||||||
|
V[2:end-1, 2:end-1] .+= 0.1 .* fv
|
||||||
|
|
||||||
return U
|
return U
|
||||||
end
|
end
|
||||||
|
|
||||||
function multi_step!(state, n_steps, heat_obs::Observable, params_obs::Observable; dx=1)
|
end # Module end
|
||||||
for _ in 1:n_steps
|
|
||||||
heat_obs[] = step!(state[1], state[2], params_obs; dx=1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
module GrayScottSolver
|
||||||
|
|
||||||
include("utils/constants.jl")
|
include("utils/constants.jl")
|
||||||
include("utils/laplacian.jl")
|
include("utils/laplacian.jl")
|
||||||
|
|
||||||
|
|
@ -6,7 +8,7 @@ using Observables
|
||||||
using .Constants
|
using .Constants
|
||||||
using .Laplacian
|
using .Laplacian
|
||||||
|
|
||||||
function step!(U, V, params_obs::Observable; dx=1)
|
function step_gray_scott!(U, V, params_obs::Observable; dx=1)
|
||||||
# Extract parameters
|
# Extract parameters
|
||||||
p = params_obs[]
|
p = params_obs[]
|
||||||
Du, Dv = p.Du, p.Dv
|
Du, Dv = p.Du, p.Dv
|
||||||
|
|
@ -42,8 +44,5 @@ function step!(U, V, params_obs::Observable; dx=1)
|
||||||
|
|
||||||
return U # for visualization
|
return U # for visualization
|
||||||
end
|
end
|
||||||
function multi_step!(state, n_steps, heat_obs::Observable, params_obs::Observable; dx=1)
|
|
||||||
for _ in 1:n_steps
|
end # Module end
|
||||||
heat_obs[] = step!(state[1], state[2], params_obs; dx=1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -10,11 +10,6 @@ struct FHNParams <: PDEParams
|
||||||
ϵ::Float64
|
ϵ::Float64
|
||||||
a::Float64
|
a::Float64
|
||||||
b::Float64
|
b::Float64
|
||||||
|
|
||||||
# Inner constructor that takes keyword arguments
|
|
||||||
# The semicolon ';' separates positional arguments from keyword arguments
|
|
||||||
FHNParams(; N::Int, dx::Float64, Du::Float64, Dv::Float64, ϵ::Float64, a::Float64, b::Float64) =
|
|
||||||
new(N, dx, Du, Dv, ϵ, a, b)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
struct GSParams <: PDEParams
|
struct GSParams <: PDEParams
|
||||||
|
|
@ -27,6 +22,18 @@ struct GSParams <: PDEParams
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
export PDEParams, FHNParams, GSParams
|
struct CombinedPDEParams <: PDEParams
|
||||||
|
N::Int
|
||||||
|
dx::Float64
|
||||||
|
Du::Float64
|
||||||
|
Dv::Float64
|
||||||
|
F::Float64
|
||||||
|
k::Float64
|
||||||
|
ϵ::Float64
|
||||||
|
a::Float64
|
||||||
|
b::Float64
|
||||||
|
end
|
||||||
|
|
||||||
|
export PDEParams, FHNParams, GSParams, CombinedPDEParams
|
||||||
|
|
||||||
end # module Constants
|
end # module Constants
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,18 @@
|
||||||
module Visualization
|
module Visualization
|
||||||
include("gray_scott_solver.jl")
|
|
||||||
#include("fhn_solver.jl")
|
|
||||||
|
|
||||||
using GLMakie, Observables, Makie
|
include("../src/utils/constants.jl")
|
||||||
|
include("gray_scott_solver.jl")
|
||||||
|
include("fhn_solver.jl")
|
||||||
|
|
||||||
|
using Observables, Makie, GLMakie
|
||||||
|
using .Constants
|
||||||
|
using .GrayScottSolver: step_gray_scott!
|
||||||
|
using .FHNSolver: step_fhn!
|
||||||
|
|
||||||
|
const STEP_FUNCTIONS = Dict(
|
||||||
|
:gray_scott => GrayScottSolver.step_gray_scott!,
|
||||||
|
:fhn => FHNSolver.step_fhn!
|
||||||
|
)
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -34,9 +44,11 @@ function reset!(U, V, heat_obs)
|
||||||
heat_obs[] = copy(U)
|
heat_obs[] = copy(U)
|
||||||
end
|
end
|
||||||
|
|
||||||
function param_box!(grid, row, labeltxt, observable::Observable)
|
function param_box!(grid, row, labeltxt, observable::Observable; col=1)
|
||||||
Label(grid[row, 1], labeltxt)
|
label_cell = 2 * col - 1
|
||||||
box = Textbox(grid[row, 2], validator=Float64, width=50, placeholder=labeltxt, stored_string="$(observable[])")
|
textbox_cell = 2 * col
|
||||||
|
Label(grid[row, label_cell], labeltxt)
|
||||||
|
box = Textbox(grid[row, textbox_cell], 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)
|
||||||
|
|
@ -45,13 +57,27 @@ function param_box!(grid, row, labeltxt, observable::Observable)
|
||||||
@warn "Invalid input for $labeltxt: $s"
|
@warn "Invalid input for $labeltxt: $s"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
on(observable) do val
|
||||||
|
box.displayed_string[] = string(val)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function multi_step!(state, n_steps, heat_obs::Observable, params_obs::Observable; step_method=step_gray_scott!, dx=1)
|
||||||
|
for _ in 1:n_steps
|
||||||
|
heat_obs[] = step_method(state[1], state[2], params_obs; dx=1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
||||||
|
|
||||||
reset!(U, V, heat_obs)
|
reset!(U, V, 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])
|
dropdown = Menu(fig, options=collect(zip(["Gray-Scott", "FHN"], [:gray_scott, :fhn])))
|
||||||
|
gh[1, 1] = dropdown
|
||||||
|
ax = Axis(gh[2, 1])
|
||||||
|
|
||||||
hm = Makie.heatmap!(ax, heat_obs, colormap=:viridis)
|
hm = Makie.heatmap!(ax, heat_obs, colormap=:viridis)
|
||||||
deactivate_interaction!(ax, :rectanglezoom)
|
deactivate_interaction!(ax, :rectanglezoom)
|
||||||
ax.aspect = DataAspect()
|
ax.aspect = DataAspect()
|
||||||
|
|
@ -59,33 +85,39 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
||||||
run_label = Observable{String}("Run")
|
run_label = Observable{String}("Run")
|
||||||
stepsize = Observable(30)
|
stepsize = Observable(30)
|
||||||
spoint = select_point(ax.scene)
|
spoint = select_point(ax.scene)
|
||||||
|
step_method = Observable{Function}(step_gray_scott!)
|
||||||
|
|
||||||
# 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=50, label="Step")
|
||||||
btn_start = Button(buttongrid[1, 2], width=50, label=run_label)
|
btn_start = Button(buttongrid[1, 2], width=50, label=run_label)
|
||||||
btn_reset = Button(buttongrid[1, 3], width=50, label="Reset")
|
btn_reset = Button(buttongrid[1, 3], width=50, label="Reset")
|
||||||
slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:100, format="{}x", width=350, startvalue=stepsize[]))
|
slidergrid = SliderGrid(fig[3, 1], (label="Speed", range=1:1:100, format="{}x", width=350, startvalue=stepsize[]), tellwidth=false)
|
||||||
|
|
||||||
speed_slider = slidergrid.sliders[1].value
|
speed_slider = slidergrid.sliders[1].value
|
||||||
|
|
||||||
|
# place all the parameter boxes
|
||||||
|
gh[2, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
|
||||||
|
|
||||||
gh[1, 2] = textboxgrid = GridLayout(ax.scene, tellwidth=false)
|
param_box!(textboxgrid, 1, "Du", param_obs_map.Du, col=1)
|
||||||
rowsize!(gh, 1, Relative(1.0))
|
param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv, col=1)
|
||||||
|
param_box!(textboxgrid, 3, "Feed", param_obs_map.F, col=1)
|
||||||
|
param_box!(textboxgrid, 4, "Kill", param_obs_map.k, col=1)
|
||||||
|
|
||||||
|
# FHN column (col 2)
|
||||||
|
param_box!(textboxgrid, 1, "Du", param_obs_map.Du, col=2)
|
||||||
|
param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv, col=2)
|
||||||
|
param_box!(textboxgrid, 3, "ϵ", param_obs_map.ϵ, col=2)
|
||||||
|
param_box!(textboxgrid, 4, "a", param_obs_map.a, col=2)
|
||||||
|
param_box!(textboxgrid, 5, "b", param_obs_map.b, col=2)
|
||||||
|
|
||||||
param_box!(textboxgrid, 1, "Du", param_obs_map.Du)
|
rowsize!(gh, 1, Fixed(50)) # small row for the menu
|
||||||
param_box!(textboxgrid, 2, "Dv", param_obs_map.Dv)
|
rowsize!(gh, 2, Relative(1.0))
|
||||||
|
for c in 1:4
|
||||||
if haskey(param_obs_map, :F)
|
colsize!(textboxgrid, c, Relative(1.0 / 4.0))
|
||||||
param_box!(textboxgrid, 3, "Feed", param_obs_map.F)
|
|
||||||
param_box!(textboxgrid, 4, "kill", param_obs_map.k)
|
|
||||||
elseif haskey(param_obs_map, :ϵ)
|
|
||||||
param_box!(textboxgrid, 3, "ϵ", param_obs_map.ϵ)
|
|
||||||
param_box!(textboxgrid, 4, "a", param_obs_map.a)
|
|
||||||
param_box!(textboxgrid, 5, "b", param_obs_map.b)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Events ##############################################################
|
||||||
# Timer and state for animation
|
# Timer and state for animation
|
||||||
running = Observable(false)
|
running = Observable(false)
|
||||||
|
|
||||||
|
|
@ -102,7 +134,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
||||||
end
|
end
|
||||||
# Button Listeners
|
# 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; step_method=step_method[])
|
||||||
end
|
end
|
||||||
|
|
||||||
on(btn_start.clicks) do _
|
on(btn_start.clicks) do _
|
||||||
|
|
@ -111,7 +143,7 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
||||||
|
|
||||||
on(btn_start.clicks) do _
|
on(btn_start.clicks) do _
|
||||||
@async while running[]
|
@async while running[]
|
||||||
multi_step!((U, V), stepsize[], heat_obs, params_obs)
|
multi_step!((U, V), stepsize[] * 5, heat_obs, params_obs; step_method=step_method[])
|
||||||
sleep(0.0015) # ~20 FPS
|
sleep(0.0015) # ~20 FPS
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -127,7 +159,6 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
x, y = pt
|
x, y = pt
|
||||||
println("params_obs[].N, ", params_obs[].N)
|
|
||||||
i, j = coord_to_index(x, y, params_obs[].N)
|
i, j = coord_to_index(x, y, params_obs[].N)
|
||||||
|
|
||||||
# get corners of square that will get filled with concentration
|
# get corners of square that will get filled with concentration
|
||||||
|
|
@ -142,6 +173,24 @@ function build_ui(U, V, param_obs_map::NamedTuple, params_obs, heat_obs)
|
||||||
|
|
||||||
heat_obs[] = copy(U)
|
heat_obs[] = copy(U)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
on(dropdown.selection) do sel
|
||||||
|
if sel isa Tuple
|
||||||
|
label, selected_model = sel
|
||||||
|
else
|
||||||
|
selected_model = sel
|
||||||
|
label = string(sel)
|
||||||
|
end
|
||||||
|
|
||||||
|
@info "Selected model: $label → $selected_model"
|
||||||
|
|
||||||
|
if haskey(STEP_FUNCTIONS, selected_model)
|
||||||
|
step_method[] = STEP_FUNCTIONS[selected_model]
|
||||||
|
else
|
||||||
|
@warn "Unknown model selected: $selected_model"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return fig
|
return fig
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue